/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Tencent is pleased to support the open source community by making behaviac available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at http://opensource.org/licenses/BSD-3-Clause
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and limitations under the License.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef _ENGINESERVICES_METHOD_H_
#define _ENGINESERVICES_METHOD_H_

#include "behaviac/base/core/staticassert.h"
#include "behaviac/base/core/thread/asyncvalue.h"
#include "behaviac/base/meta/meta.h"
#include "behaviac/base/meta/isptr.h"

#include "behaviac/base/base.h"
#include "behaviac/base/object/typehandler.h"

#include "behaviac/property/property.h"

#include "behaviac/network/network.h"


class CTagObject;

namespace behaviac
{
	namespace Meta
	{
		template <typename T, bool bAgent>
		class ParamTypeConverterAgent
		{
		public:
			typedef REAL_BASETYPE(T)		BaseType;
			typedef POINTER_TYPE(T)			PointerType;
			//typedef T*						BaseType;
			//typedef T**						PointerType;
		};

		template <typename T>
		class ParamTypeConverterAgent<T, true>
		{
			typedef REAL_BASETYPE(T)		TBaseType;
		public:
			typedef TBaseType*		BaseType;
			typedef TBaseType**		PointerType;
		};

		template <typename T>
		class ParamTypeConverter<T, true>
		{
			enum { BIsAgent = IsAgent<T>::Result };
		public:
			typedef typename ParamTypeConverterAgent<T, BIsAgent>::BaseType			BaseType;
			typedef typename ParamTypeConverterAgent<T, BIsAgent>::PointerType		PointerType;
		};
	}
}

template <typename MemberType, bool bAgent>
struct SaveToXMLDispatcher
{
	static void SaveToXML(ISerializableNode& xmlNode, const MemberType& value, const char* paramName)
	{
		GenericTypeHandler<MemberType>::SaveToXML(xmlNode, const_cast<MemberType&>(value), 0, paramName);
	}
};

template <typename MemberType>
struct SaveToXMLDispatcher<MemberType, true>
{
	static void SaveToXML(ISerializableNode& xmlNode, const MemberType& value, const char* paramName)
	{
		GenericTypeHandler<MemberType>::SaveToXML(xmlNode, value, 0, paramName);
	}
};

template <typename T>
class ParamVariablePrimitive
{
	//if agent, to save the ptr
	typedef STORED_TYPE(T) StoredType_t;
public:
	ParamVariablePrimitive() : bDefaultValid(false), prop(0)
	{}

	~ParamVariablePrimitive()
	{
		BEHAVIAC_DELETE(this->prop);
		this->prop = 0;
	}

	bool IsDefaultValid() const
	{
		return this->bDefaultValid;
	}

	void SetValue(const T& v)
	{
		this->bDefaultValid = true;
		this->param = v;
		//if (this->prop)
		//{
		//	this->prop->SetValue(v);
		//}
	}

	const T& GetValue() const
	{
		//return this->param;
		return GetValueSelector<T, behaviac::Meta::IsAgent<T>::Result, behaviac::Meta::IsPtr<T>::Result>::GetValue(this->param);
	}
	//ParamVariablePrimitive(const ParamVariablePrimitive& copy) : param(copy.param), bDefaultValid(copy.bDefaultValid)
	//{
	//	if (copy.prop)
	//	{
	//		this->prop = copy.prop->clone();
	//	}
	//	else
	//	{
	//		this->prop = 0;
	//	}
	//}

	void operator=(const ParamVariablePrimitive& copy)
	{
		this->bDefaultValid = copy.bDefaultValid;
		this->param = copy.param;
		if (copy.prop)
		{
			this->prop = copy.prop->clone();
		}
		else
		{
			this->prop = 0;
		}
	}

	void LoadFromXML(CTagObject* parent, const ISerializableNode& xmlNode, const char* paramName)
	{
		BEHAVIAC_UNUSED_VAR(parent);

		CSerializationID id(paramName);
		const char* str = xmlNode.getAttrRaw(id);
		if (str)
		{
			//str[0] = '"', then it is a string
			if (str[0] != '"' && strchr(str, ' '))
			{
				behaviac::vector<behaviac::string> tokens;
				behaviac::StringUtils::SplitIntoArray(str, " ", tokens);

				if (tokens.size() == 2)
				{
					//int AgentTest::Property1
					this->prop = behaviac::Property::Create(tokens[0].c_str(), tokens[1].c_str(), 0, false, false);
				}
				else
				{
					//static int AgentTest::Property6
					BEHAVIAC_ASSERT(tokens[0] == "static");
					this->prop = behaviac::Property::Create(tokens[1].c_str(), tokens[2].c_str(), 0, true, false);				
				}
			}
			else
			{
				//BEHAVIAC_UNUSED_VAR(parent);
				//GenericTypeHandler<T>::LoadFromXML(xmlNode, param, 0, paramName);
				if (!behaviac::StringUtils::FromString(str, this->param))
				{
					BEHAVIAC_LOG1(BEHAVIAC_LOG_WARNING, "Fail read param count from behaviac::string:%s\n", str);
				}
			}
		}
	}

	void SaveToXML(const CTagObject* parent, ISerializableNode& xmlNode, const char* paramName)
	{
		BEHAVIAC_UNUSED_VAR(parent);

		const T& value = GetValue(parent, 0);
		//SaveToXMLDispatcher<T, behaviac::Meta::IsAgent<REAL_BASETYPE(T)>::Result>::
		//	SaveToXML(xmlNode, const_cast<T&>(value), paramName);
		GenericTypeHandler<T>::SaveToXML(xmlNode, const_cast<T&>(value), 0, paramName);
	}

	const T& GetValue(const CTagObject* parent, const CTagObject* parHolder) const;
	//void SetVariableRegistry(const CTagObject* parent, const CTagObject* parHolder);
	void SetVariableRegistry(const CTagObject* parHolder, const T& value);

protected:
	bool					bDefaultValid;
	StoredType_t			param;
	behaviac::Property*		prop;
};

namespace behaviac
{
namespace StringUtils
{
	BEHAVIAC_API bool ParseForStruct(const char* str, behaviac::string& strT, behaviac::map<CStringID, behaviac::Property*>& props);
}
}

template <typename T>
class ParamVariablePtrPrimitive : public ParamVariablePrimitive<T>
{
public:
	ParamVariablePtrPrimitive()
	{
		this->param = 0;
	}

	void LoadFromXML(CTagObject* parent, const ISerializableNode& xmlNode, const char* paramName)
	{
		CSerializationID id(paramName);
		const char* str = xmlNode.getAttrRaw(id);

		if (str && string_icmp(str, "null") == 0)
		{
			BEHAVIAC_ASSERT(this->param == 0);

			return;
		}
	
		ParamVariablePrimitive<T>::LoadFromXML(parent, xmlNode, paramName);
	}
};

template <typename T>
class ParamVariableStruct : public ParamVariablePrimitive<T>
{
public:
	ParamVariableStruct()
	{}

	~ParamVariableStruct()
	{
		for (PropsMap_t::iterator it = this->m_props.begin();
			it !=this->m_props.end(); ++it)
		{
			behaviac::Property* p = it->second;
			BEHAVIAC_DELETE(p);
		}

		this->m_props.clear();
	}

	void LoadFromXML(CTagObject* parent, const ISerializableNode& xmlNode, const char* paramName)
	{
		BEHAVIAC_UNUSED_VAR(parent);

		CSerializationID id(paramName);
		const char* str = xmlNode.getAttrRaw(id);
		if (str)
		{
			if (*str != '{')
			{
				ParamVariablePrimitive<T>::LoadFromXML(parent, xmlNode, paramName);
			}
			else
			{
				behaviac::string strT;

				//{bLive=false;color=Red;name=0;weight=float par_float;}
				//{bLive=false;color=Red;name=0;weight=static int AgentTest::Property6;}
				//skip par and record par
				if (behaviac::StringUtils::ParseForStruct(str, strT, this->m_props))
				{
					if (!behaviac::StringUtils::FromString(strT.c_str(), this->param))
					{
						BEHAVIAC_LOG1(BEHAVIAC_LOG_WARNING, "Fail read param count from behaviac::string:%s\n", str);
					}
				}
			}
		}
	}

	const T& GetValue() const
	{
		return this->param;
	}

	const T& GetValue(const CTagObject* parent, const CTagObject* parHolder) const;

	void operator=(const ParamVariableStruct& copy)
	{
		ParamVariablePrimitive<T>* pBase = (ParamVariablePrimitive<T>*)this;
		*pBase = *(ParamVariablePrimitive<T>*)&copy;

		for (PropsMap_t::iterator it = this->m_props.begin();
			it !=this->m_props.end(); ++it)
		{
			const CStringID& propId = it->first;
			behaviac::Property* p = it->second;

			this->m_props[propId] = p->clone();
		}
	}

	void SetVariableRegistry(const CTagObject* parHolder, const T& value);

private:
	typedef behaviac::map<CStringID, behaviac::Property*> PropsMap_t;
	PropsMap_t		m_props;
};

template <typename T, bool bIsPtr>
struct ParamVariablePtrSelector
{
	typedef ParamVariablePrimitive<T> ParamVariableType;
};

template <typename T>
struct ParamVariablePtrSelector<T, true>
{
	typedef ParamVariablePtrPrimitive<T> ParamVariableType;
};


template <typename T, bool bStruct>
struct ParamVariableSelector
{
	//typedef ParamVariablePrimitive<T> ParamVariableType;
	typedef typename ParamVariablePtrSelector<T, behaviac::Meta::IsPtr<T>::Result>::ParamVariableType ParamVariableType;
};

template <typename T>
struct ParamVariableSelector<T, true>
{
	typedef ParamVariableStruct<T> ParamVariableType;
};

template <typename T>
struct ParamVariable : public ParamVariableSelector<T, behaviac::Meta::HasFromString<T>::Result>::ParamVariableType
{

};


class IMethodReturn
{
public:
	IMethodReturn() : m_methodPtr(0), m_methodPtr_Static(0)
	{}

	IMethodReturn(const IMethodReturn& copy)
	{
		this->m_methodPtr = copy.m_methodPtr;
		this->m_methodPtr_Static = copy.m_methodPtr_Static;
	}

	virtual ~IMethodReturn()
	{

	}

	virtual IMethodReturn* clone() = 0;

	virtual void run(void* ret, const CTagObject* parent, behaviac::IAsyncValue& param)
	{
		BEHAVIAC_UNUSED_VAR(ret);
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(param);
	}
protected:
	void (IMethodReturn::*m_methodPtr)();

	void (*m_methodPtr_Static)();
};

template <typename RTYPE, typename ObjectType, typename ParamType>
class CMethodReturn : public IMethodReturn
{
public:
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CMethodReturn);
	CMethodReturn() : IMethodReturn()
	{}

	virtual ~CMethodReturn()
	{

	}

	CMethodReturn(const CMethodReturn& copy) : IMethodReturn(copy)
	{
	}

	virtual IMethodReturn* clone()
	{
		return BEHAVIAC_NEW CMethodReturn(*this);
	}

	void SetHandler(RTYPE(ObjectType::*methodPtr)(ParamType))
	{
		typedef void (IMethodReturn::*MethodPtr_t)();
		this->m_methodPtr = reinterpret_cast<MethodPtr_t>(methodPtr);
	}

	virtual void run(void* ret, const CTagObject* parent, behaviac::IAsyncValue& param)
	{
		typedef RTYPE(ObjectType::*MethodPtr_t)(ParamType);
		behaviac::AsyncValue<ParamType>& paramValue = (behaviac::AsyncValue<ParamType>&)param;
		MethodPtr_t methodPtr = (MethodPtr_t)this->m_methodPtr;
		RTYPE result = (((ObjectType*)parent)->*methodPtr)(paramValue.get());
		*(RTYPE*)ret = result;
	}
};


template <typename RTYPE, typename ObjectType>
class CMethodReturn<RTYPE, ObjectType, void> : public IMethodReturn
{
public:
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CMethodReturn);
	CMethodReturn() : IMethodReturn()
	{}

	CMethodReturn(const CMethodReturn& copy) : IMethodReturn(copy)
	{
	}

	virtual ~CMethodReturn()
	{

	}

	virtual IMethodReturn* clone()
	{
		return BEHAVIAC_NEW CMethodReturn(*this);
	}

	void SetHandler(RTYPE(ObjectType::*methodPtr)())
	{
		typedef void (IMethodReturn::*MethodPtr_t)();
		this->m_methodPtr = reinterpret_cast<MethodPtr_t>(methodPtr);
	}

	virtual void run(void* ret, const CTagObject* parent, behaviac::IAsyncValue& param)
	{
		typedef RTYPE(ObjectType::*MethodPtr_t)();
		MethodPtr_t methodPtr = (MethodPtr_t)this->m_methodPtr;
		RTYPE result = (((ObjectType*)parent)->*methodPtr)();
		*(RTYPE*)ret = result;
	}
};


template <typename RTYPE, typename ParamType>
class CMethodReturnStatic : public IMethodReturn
{
public:
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CMethodReturnStatic);
	CMethodReturnStatic() : IMethodReturn()
	{}

	CMethodReturnStatic(const CMethodReturnStatic& copy) : IMethodReturn(copy)
	{
	}

	virtual IMethodReturn* clone()
	{
		return BEHAVIAC_NEW CMethodReturnStatic(*this);
	}

	void SetHandler(RTYPE(*methodPtr)(ParamType))
	{
		typedef void (*MethodPtr_t)();
		this->m_methodPtr_Static = reinterpret_cast<MethodPtr_t>(methodPtr);
	}

	virtual void run(void* ret, const CTagObject* parent, behaviac::IAsyncValue& param)
	{
		BEHAVIAC_UNUSED_VAR(parent);

		typedef RTYPE(*MethodPtr_t)(ParamType);
		behaviac::AsyncValue<ParamType>& paramValue = (behaviac::AsyncValue<ParamType>&)param;
		MethodPtr_t methodPtr = (MethodPtr_t)this->m_methodPtr_Static;
		RTYPE result = (*methodPtr)(paramValue.get());
		*(RTYPE*)ret = result;
	}
};


template <typename RTYPE>
class CMethodReturnStatic<RTYPE, void> : public IMethodReturn
{
public:
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CMethodReturnStatic);
	CMethodReturnStatic() : IMethodReturn()
	{}

	CMethodReturnStatic(const CMethodReturnStatic& copy) : IMethodReturn(copy)
	{
	}

	virtual IMethodReturn* clone()
	{
		return BEHAVIAC_NEW CMethodReturnStatic(*this);
	}

	void SetHandler(RTYPE(*methodPtr)())
	{
		typedef void (*MethodPtr_t)();
		this->m_methodPtr_Static = reinterpret_cast<MethodPtr_t>(methodPtr);
	}

	virtual void run(void* ret, const CTagObject* parent, behaviac::IAsyncValue& param)
	{
		BEHAVIAC_UNUSED_VAR(parent);        
		BEHAVIAC_UNUSED_VAR(param);        

		typedef RTYPE(*MethodPtr_t)();
		MethodPtr_t methodPtr = (MethodPtr_t)this->m_methodPtr_Static;
		RTYPE result = (*methodPtr)();
		*(RTYPE*)ret = result;
	}
};


class CCheckReturn
{
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CCheckReturn);
public:
	CCheckReturn() : m_method(0)
	{}

	CCheckReturn(const CCheckReturn& copy)
	{
		if (copy.m_method)
		{
			this->m_method = copy.m_method->clone();
		}
		else
		{
			this->m_method = 0;
		}
	}


	CCheckReturn* clone()
	{
		return BEHAVIAC_NEW CCheckReturn(*this);
	}


	~CCheckReturn()
	{
		BEHAVIAC_DELETE(m_method);
	}

	template <typename RTYPE, typename ObjectType, typename ParamType>
	void SetHandler(RTYPE(ObjectType::*methodPtr)(ParamType))
	{
		typedef CMethodReturn<RTYPE, ObjectType, ParamType> MethodType;
		MethodType* method = BEHAVIAC_NEW MethodType();
		method->SetHandler(methodPtr);
		this->m_method = method;
	}

	template <typename RTYPE, typename ObjectType>
	void SetHandler(RTYPE(ObjectType::*methodPtr)())
	{
		typedef CMethodReturn<RTYPE, ObjectType, void> MethodType;
		MethodType* method = BEHAVIAC_NEW MethodType();
		method->SetHandler(methodPtr);
		this->m_method = method;
	}

	template <typename RTYPE, typename ParamType>
	void SetHandler(RTYPE(*methodPtr)(ParamType))
	{
		typedef CMethodReturnStatic<RTYPE, ParamType> MethodType;
		MethodType* method = BEHAVIAC_NEW MethodType();
		method->SetHandler(methodPtr);
		this->m_method = method;
	}

	template <typename RTYPE>
	void SetHandler(RTYPE(*methodPtr)())
	{
		typedef CMethodReturnStatic<RTYPE, void> MethodType;
		MethodType* method = BEHAVIAC_NEW MethodType();
		method->SetHandler(methodPtr);
		this->m_method = method;
	}

	template <typename RTYPE>
	void run(RTYPE& ret, const CTagObject* parent, behaviac::IAsyncValue& param)
	{
		this->m_method->run(&ret, parent, param);
	}
private:
	IMethodReturn*	m_method;
};

#define CMETHODBASE_RANGE_MIN_DEFAULT (-90000000.f)
#define CMETHODBASE_RANGE_MAX_DEFAULT (90000000.f)

struct DefaultParam_t
{
	int type_;

	union 
	{
		bool				b_;
		char				c_;
		unsigned char		uc_;
		short				s_;
		unsigned short		us_;
		int					i_;
		unsigned int		ui_;
		long				l_;
		unsigned long		ul_;
		long long			ll_;
		unsigned long long	ull_;
		float				f_;
		double				d_;
		void*				v_;
	};

	behaviac::string		str_;

	/*
	please specialize it for your type

	template <>
	inline EnumTest DefaultParam_t::GetValue<EnumTest>() const
	{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<short>());
	return (EnumTest)this->i_;
	}
	*/
	template <typename T>
	T GetValue() const
	{
		BEHAVIAC_ASSERT(0, "please specialize this function for your type");
		static T t;
		return t;
	}

	bool IsValid() const
	{
		return this->type_ != 0;
	}

	DefaultParam_t() : type_(0), ull_(0)
	{

	}

	DefaultParam_t(bool p) : b_(p)
	{
		type_ = GetClassTypeNumberId<bool>();
	}

	DefaultParam_t(char p) : c_(p)
	{
		type_ = GetClassTypeNumberId<char>();
	}

	DefaultParam_t(unsigned char p) : uc_(p)
	{
		type_ = GetClassTypeNumberId<unsigned char>();
	}

	DefaultParam_t(short p) : s_(p)
	{
		type_ = GetClassTypeNumberId<short>();
	}

	DefaultParam_t(unsigned short p) : us_(p)
	{
		type_ = GetClassTypeNumberId<unsigned short>();
	}

	DefaultParam_t(int p) : i_(p)
	{
		type_ = GetClassTypeNumberId<int>();
	}

	DefaultParam_t(unsigned int p) : ui_(p)
	{
		type_ = GetClassTypeNumberId<unsigned int>();
	}

	DefaultParam_t(long p) : l_(p)
	{
		type_ = GetClassTypeNumberId<long>();
	}

	DefaultParam_t(unsigned long p) : ul_(p)
	{
		type_ = GetClassTypeNumberId<unsigned long>();
	}

	DefaultParam_t(long long p) : ll_(p)
	{
		type_ = GetClassTypeNumberId<long long>();
	}

	DefaultParam_t(unsigned long long p) : ull_(p)
	{
		type_ = GetClassTypeNumberId<unsigned long long>();
	}

	DefaultParam_t(float p) : f_(p)
	{
		type_ = GetClassTypeNumberId<float>();
	}

	DefaultParam_t(double p) : d_(p)
	{
		type_ = GetClassTypeNumberId<double>();
	}

	DefaultParam_t(const char*p) : str_(p)
	{
		type_ = GetClassTypeNumberId<behaviac::string>();
	}
};


template <>
inline bool DefaultParam_t::GetValue<bool>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<bool>());
	return this->b_;
}

template <>
inline char DefaultParam_t::GetValue<char>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<char>());
	return this->c_;
}

template <>
inline unsigned char DefaultParam_t::GetValue<unsigned char>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<unsigned char>());
	return this->uc_;
}

template <>
inline short DefaultParam_t::GetValue<short>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<short>());
	return this->s_;
}

template <>
inline unsigned short DefaultParam_t::GetValue<unsigned short>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<unsigned short>());
	return this->us_;
}


template <>
inline int DefaultParam_t::GetValue<int>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<int>());
	return this->i_;
}

template <>
inline unsigned int DefaultParam_t::GetValue<unsigned int>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<unsigned int>());
	return this->ui_;
}

template <>
inline long DefaultParam_t::GetValue<long>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<long>());
	return this->l_;
}

template <>
inline unsigned long DefaultParam_t::GetValue<unsigned long>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<unsigned long>());
	return this->ul_;
}

template <>
inline long long DefaultParam_t::GetValue<long long>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<long long>());
	return this->ll_;
}

template <>
inline unsigned long long DefaultParam_t::GetValue<unsigned long long>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<unsigned long long>());
	return this->ull_;
}

template <>
inline float DefaultParam_t::GetValue<float>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<float>());
	return this->f_;
}

template <>
inline double DefaultParam_t::GetValue<double>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<double>());
	return this->d_;
}

template <>
inline behaviac::string DefaultParam_t::GetValue<behaviac::string>() const
{
	//BEHAVIAC_ASSERT(this->type_ == GetClassTypeNumberId<behaviac::string>());
	return this->str_;
}

/////////////////////////////////////////////////////////
///////////////     METHOD INTERFACE     ////////////////
/////////////////////////////////////////////////////////
class BEHAVIAC_API CMethodBase
{
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CMethodBase);

public:
	const static short KMETHOD_NAMEDEVENT = 0x0001;

	CMethodBase(const char* propertyName, const char* classFullName) : m_classFullName(classFullName), m_propertyName(propertyName), 
		m_propertyID(propertyName), m_checkReturnTask(0), m_return(0), m_parentType(PT_INVALID), m_bStatic(false), m_flag(0), m_netRole(behaviac::NET_ROLE_DEFAULT)
	{
		BEHAVIAC_ASSERT(m_classFullName);
	}

	CMethodBase(const CMethodBase& copy) : m_classFullName(copy.m_classFullName), m_instanceName(copy.m_instanceName),
		m_propertyName(copy.m_propertyName), m_propertyID(copy.m_propertyID), m_displayName(copy.m_displayName), m_desc(copy.m_desc),
		m_parentType(copy.m_parentType), m_bStatic(copy.m_bStatic), m_flag(copy.m_flag), m_netRole(copy.m_netRole)
	{
		if (copy.m_checkReturnTask)
		{
			this->m_checkReturnTask = copy.m_checkReturnTask->clone();
		}
		else
		{
			this->m_checkReturnTask = 0;
		}

		if (copy.m_return)
		{
			this->m_return = copy.m_return->clone();
		}
		else
		{
			this->m_return = 0;
		}
	}

	virtual ~CMethodBase()
	{
		BEHAVIAC_DELETE(this->m_checkReturnTask);
		BEHAVIAC_DELETE(this->m_return);
	}

	virtual void LoadFromXML(CTagObject* parent, const ISerializableNode& xmlNode) = 0;
	virtual void SaveToXML(const CTagObject* parent, ISerializableNode& xmlNode) = 0;
	virtual void GetUiInfo(CTagTypeDescriptor::TypesMap_t* types, const CTagObject* parent, const XmlNodeRef& xmlNode) = 0;

	inline const CSerializationID& GetID() const
	{
		return m_propertyID;
	}

	void SetFlag(short flag)
	{
		this->m_flag = flag;
		if (this->m_flag)
		{
			//getter, return type can't be void
			BEHAVIAC_ASSERT(this->m_return && !this->m_return->IsVoid(), "getter should have a valid return.");
		}
	}

	CMethodBase& DISPLAYNAME(const wchar_t* displayName)
	{
		BEHAVIAC_UNUSED_VAR(displayName);

		if (displayName)
		{
			m_displayName = displayName;
		}

		return *this;
	}

	CMethodBase& DESC(const wchar_t* paramDesc)
	{
		BEHAVIAC_UNUSED_VAR(paramDesc);

		if (paramDesc)
		{
			m_desc = paramDesc;
		}

		return *this;
	}

	/// deprecated, to use PARAM_DISPLAY_INFO
	virtual CMethodBase& PARAM_DISPLAYNAME(const wchar_t* paramDisplayName)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);
		BEHAVIAC_ASSERT(0, "no params!");
		return *this;
	}

	/// deprecated, to use PARAM_DISPLAY_INFO
	virtual CMethodBase& PARAM_DESC(const wchar_t* paramDesc)
	{
		BEHAVIAC_UNUSED_VAR(paramDesc);
		BEHAVIAC_ASSERT(0, "no params!");
		return *this;
	}

	virtual CMethodBase& PARAM_DISPLAY_INFO(const wchar_t* paramDisplayName, const wchar_t* paramDesc = 0, const DefaultParam_t& defaultParam = DefaultParam_t(), float rangeMin = CMETHODBASE_RANGE_MIN_DEFAULT, float rangeMax = CMETHODBASE_RANGE_MAX_DEFAULT)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);
		BEHAVIAC_UNUSED_VAR(paramDesc);
		BEHAVIAC_UNUSED_VAR(defaultParam);
		BEHAVIAC_UNUSED_VAR(rangeMin);
		BEHAVIAC_UNUSED_VAR(rangeMax);

		BEHAVIAC_ASSERT(0, "no params!");
		return *this;
	}
#if BEHAVIAC_ENABLE_NETWORKD
	CMethodBase& NETROLE(behaviac::NetworkRole netRole);
	void SubsribeToNetwork(behaviac::Agent* pAgent);
	void UnSubsribeToNetwork(behaviac::Agent* pAgent);
#endif//#if BEHAVIAC_ENABLE_NETWORKD

	template <typename R, typename ObjectType, typename P>
	CMethodBase& AddResultHanlder(R(ObjectType::*methodPtr)(P))
	{
		BEHAVIAC_ASSERT(methodPtr);

		{
			CCheckReturn* pMethod = BEHAVIAC_NEW CCheckReturn();
			pMethod->SetHandler(methodPtr);
			this->m_checkReturnTask = pMethod;
		}

		typedef behaviac::AsyncValue<R> ReturnType;
		this->m_return = BEHAVIAC_NEW ReturnType();
		return *this;
	}

	template <typename R, typename ObjectType>
	CMethodBase& AddResultHanlder(R(ObjectType::*methodPtr)())
	{
		BEHAVIAC_ASSERT(methodPtr);
		{
			CCheckReturn* pMethod = BEHAVIAC_NEW CCheckReturn();
			pMethod->SetHandler(methodPtr);
			this->m_checkReturnTask = pMethod;
		}

		typedef behaviac::AsyncValue<R> ReturnType;
		this->m_return = BEHAVIAC_NEW ReturnType();
		return *this;
	}

	template <typename R, typename P>
	CMethodBase& AddResultHanlder(R(*methodPtr)(P))
	{
		BEHAVIAC_ASSERT(methodPtr);

		{
			CCheckReturn* pMethod = BEHAVIAC_NEW CCheckReturn();
			pMethod->SetHandler(methodPtr);
			this->m_checkReturnTask = pMethod;
		}

		typedef behaviac::AsyncValue<R> ReturnType;
		this->m_return = BEHAVIAC_NEW ReturnType();
		return *this;
	}

	template <typename R>
	CMethodBase& AddResultHanlder(R(*methodPtr)())
	{
		BEHAVIAC_ASSERT(methodPtr);
		{
			CCheckReturn* pMethod = BEHAVIAC_NEW CCheckReturn();
			pMethod->SetHandler(methodPtr);
			this->m_checkReturnTask = pMethod;
		}

		typedef behaviac::AsyncValue<R> ReturnType;
		this->m_return = BEHAVIAC_NEW ReturnType();
		return *this;
	}

	template <typename R>
	CMethodBase& AddResultHanlder()
	{
		typedef behaviac::AsyncValue<R> ReturnType;
		this->m_return = BEHAVIAC_NEW ReturnType();
		return *this;
	}

	CMethodBase& AddResultHanlder()
	{
		//typedef behaviac::AsyncValue<R> ReturnType;
		//this->m_return = BEHAVIAC_NEW ReturnType();
		return *this;
	}

	/**
	be careful to use this function only when you know the return type
	*/
	template <typename R>
	bool GetReturnValue(const CTagObject* parent, R& returnValue)
	{
		BEHAVIAC_UNUSED_VAR(parent); 

		if (this->m_return)
		{
			returnValue = ((behaviac::AsyncValue<R>*)this->m_return)->get();
			return true;
		}

		return false;
	}

	bool GetReturnValue(const CTagObject* parent, behaviac::Property* ret, CTagObject* parentReturn)
	{
		if (this->m_return && ret)
		{
			ret->SetFrom((behaviac::Agent*)parent, this->m_return, (behaviac::Agent*)parentReturn);
			return true;
		}

		return false;
	}

	bool ComputeReturnValue(const CTagObject* parent, behaviac::Property* ret, CTagObject* parentReturn, behaviac::EComputeOperator opr)
	{
		if (this->m_return && ret)
		{
			ret->ComputeFrom((behaviac::Agent*)parent, this->m_return, (behaviac::Agent*)parentReturn, opr);
			return true;
		}

		return false;
	}

	int CheckReturn(const CTagObject* parent, CTagObject* parentCheckResult, CMethodBase* checkResultMethod)
	{
		BEHAVIAC_UNUSED_VAR(parent); 

		if (checkResultMethod)
		{
			BEHAVIAC_ASSERT(this->m_return);
			int result = checkResultMethod->vRun(parentCheckResult, *this->m_return);

			return result;
		}

		return 0;
	}

	template <typename RTYPE>
	void CheckReturn(const CTagObject* parent, RTYPE& result)
	{
		if (this->m_checkReturnTask)
		{
			BEHAVIAC_ASSERT(this->m_return);
			this->m_checkReturnTask->run(result, parent, *this->m_return);
		}
		else if (this->m_return)
		{
			result = ((behaviac::AsyncValue<RTYPE>*)this->m_return)->get();
		}
		else
		{
			BEHAVIAC_ASSERT(false);
		}
	}

	void CheckReturn(const CTagObject* parent, bool& result)
	{
		if (this->m_checkReturnTask)
		{
			BEHAVIAC_ASSERT(this->m_return);
			this->m_checkReturnTask->run(result, parent, *this->m_return);
		}
		else if (this->m_return)
		{
			result = ((behaviac::AsyncValue<bool>*)this->m_return)->get();
		}
		else
		{
			BEHAVIAC_ASSERT(false);
		}
	}


	virtual int GetParams()
	{
		return -1;
	}

	// Invoking a method by calling an explicit function for each possible signature.
	virtual behaviac::string GetParamTypeName(uint32_t idx)
	{
		BEHAVIAC_UNUSED_VAR(idx);
		BEHAVIAC_ASSERT(!"Not Implemented");
		return "";
	}
	virtual int vRun(const CTagObject* parent, behaviac::IAsyncValue& returnResult)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(returnResult);
		BEHAVIAC_ASSERT(!"Not Implemented");

		return 0;
	};
	virtual void vCall(const CTagObject* parent)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_ASSERT(!"Not Implemented");
	};
	virtual void vCall(const CTagObject* parent, const void* param1)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(param1);
		BEHAVIAC_ASSERT(!"Not Implemented");
	};
	virtual void vCall(const CTagObject* parent, const void* param1, const void* param2)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(param1);
		BEHAVIAC_UNUSED_VAR(param2);

		BEHAVIAC_ASSERT(!"Not Implemented");
	};
	virtual void vCall(const CTagObject* parent, const void* param1, const void* param2, const void* param3)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(param1);
		BEHAVIAC_UNUSED_VAR(param2);
		BEHAVIAC_UNUSED_VAR(param3);

		BEHAVIAC_ASSERT(!"Not Implemented");
	};
	virtual void vCall(const CTagObject* parent, const void* param1, const void* param2, const void* param3, const void* param4)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(param1);
		BEHAVIAC_UNUSED_VAR(param2);
		BEHAVIAC_UNUSED_VAR(param3);
		BEHAVIAC_UNUSED_VAR(param4);

		BEHAVIAC_ASSERT(!"Not Implemented");
	};
	virtual void vCall(const CTagObject* parent, const void* param1, const void* param2, const void* param3, const void* param4, const void* param5)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(param1);
		BEHAVIAC_UNUSED_VAR(param2);
		BEHAVIAC_UNUSED_VAR(param3);
		BEHAVIAC_UNUSED_VAR(param4);
		BEHAVIAC_UNUSED_VAR(param5);

		BEHAVIAC_ASSERT(!"Not Implemented");
	};
	virtual void vCall(const CTagObject* parent, const void* param1, const void* param2, const void* param3, const void* param4, const void* param5, const void* param6)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(param1);
		BEHAVIAC_UNUSED_VAR(param2);
		BEHAVIAC_UNUSED_VAR(param3);
		BEHAVIAC_UNUSED_VAR(param4);
		BEHAVIAC_UNUSED_VAR(param5);
		BEHAVIAC_UNUSED_VAR(param6);

		BEHAVIAC_ASSERT(!"Not Implemented");
	};

	virtual behaviac::Property* CreateProperty(const char* defaultValue, bool bConst) const
	{
		BEHAVIAC_UNUSED_VAR(defaultValue);
		BEHAVIAC_UNUSED_VAR(bConst);

		return 0;
	}

	virtual CMethodBase* clone() const = 0;
	virtual void run(const CTagObject* parent, const CTagObject* parHolder) = 0;

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params) = 0;
#endif//#if BEHAVIAC_ENABLE_NETWORKD

	const char* GetName() const
	{
		return this->m_propertyName;
	}

	const behaviac::wstring& GetDisplayName() const
	{
		return this->m_displayName;
	}

	const behaviac::wstring& GetDesc() const
	{
		return this->m_desc;
	}

	const char* GetClassNameString() const
	{
		return m_classFullName;
	}

	const char* GetInstanceNameString() const
	{
		return m_instanceName.c_str();
	}

	void SetInstanceNameString(const char* name, ParentType pt)
	{
		this->m_instanceName = name;
		this->m_parentType = pt;
	}

	virtual bool IsNamedEvent() const
	{
		return false;
	}

	ParentType GetParentType() const
	{
		return this->m_parentType;
	}
protected:
	//return true then it can only used for 'action'
	bool IsActionMethodOnly() const
	{
		bool bActionMethodOnly = (this->m_checkReturnTask != 0);

		return bActionMethodOnly;
	}

protected:
	const char*						m_classFullName;
	behaviac::string				m_instanceName;
	const char*						m_propertyName;
	CSerializationID				m_propertyID;

	behaviac::wstring				m_displayName;
	behaviac::wstring				m_desc;

	CCheckReturn*					m_checkReturnTask;
	behaviac::IAsyncValue*			m_return;

	ParentType						m_parentType;

	bool							m_bStatic;

	//event
	short							m_flag;
	behaviac::NetworkRole			m_netRole;
};

template<typename T, bool bComplexType>
struct UserTypeInfo
{
	static void Export(CTagTypeDescriptor::TypesMap_t* types, bool returnType, XmlNodeRef memberNode)
	{
		BEHAVIAC_UNUSED_VAR(returnType);
		BEHAVIAC_UNUSED_VAR(memberNode);
		BEHAVIAC_UNUSED_VAR(types);
	}
};

template<typename T, bool bEnum>
struct UserTypeInfoStruct
{
	static void Export(CTagTypeDescriptor::TypesMap_t* types, XmlNodeRef memberNode)
	{
		if (types != NULL)
		{
			const char* typeName = ::GetClassTypeName((T*)0);
			if (types->find(typeName) == types->end())
			{
				RegisterPropertiesGetter<T, behaviac::Meta::HasFromString<T>::Result>::_RegisterProperties();
				const CTagObjectDescriptor& objDesc = ObjectDescriptorGettter<T, behaviac::Meta::HasFromString<T>::Result>::_GetObjectDescriptor();
				objDesc.GetMembersDescription(types, 0, memberNode);

				(*types)[typeName] = &objDesc;
			}
		}
	}
};

template<typename T>
struct UserTypeInfoStruct<T, true>
{
	static void Export(CTagTypeDescriptor::TypesMap_t* types, XmlNodeRef memberNode)
	{
		EnumClassUiInfoGetter<T, true>::GetUiInfo(types, memberNode);
	}
};

template<typename T>
struct UserTypeInfo<T, true>
{
	static void Export(CTagTypeDescriptor::TypesMap_t* types, bool returnType, XmlNodeRef memberNode)
	{
		BEHAVIAC_UNUSED_VAR(returnType);
		//if (returnType)
		//{
		//	XmlNodeRef memberNode1 = memberNode->newChild("ReturnType");
		//	const char* typeName = GetClassTypeName((T*)0);
		//	memberNode1->setAttr("Type", typeName);
		//	UserTypeInfoStruct<T, behaviac::Meta::IsEnum<T>::Result>::Export(types, memberNode1);
		//}
		//else
		{
			UserTypeInfoStruct<T, behaviac::Meta::IsEnum<T>::Result>::Export(types, memberNode);
		}
	}
};

template<typename T>
struct UserTypeInfoExport
{
	static void Export(CTagTypeDescriptor::TypesMap_t* types, bool returnType, XmlNodeRef memberNode)
	{
		UserTypeInfo<T, behaviac::Meta::IsEnum<T>::Result || behaviac::Meta::HasToString<T>::Result>::Export(types, returnType, memberNode);
	}
};
/////////////////////////////////////////////////////////
////////////////         METHOD          ////////////////
/////////////////////////////////////////////////////////

#define BEGIN_REGISTER_METHOD(propertyName, methodName)                                         \
{                                                                                           \
	CMethodBase* _property = &CMethodFactory::Create(&objectType::methodName, objectType::GetClassTypeName(), propertyName

#define END_REGISTER_METHOD()                                                                   \
	);                                                                                          \
	ms_methods.push_back (_property);                                                           \
}

#define ADD_PARAM(paramName)    ,paramName


BEHAVIAC_FORCEINLINE CMethodBase& _addMethod(behaviac::vector<class CMethodBase*>& methods, CMethodBase* _method)
{
	methods.push_back(_method);
	return *_method;
}

class MethodsContainer;

/////////////////////////////////////////////////////////
////////////////     CGenericMethod      ////////////////
/////////////////////////////////////////////////////////

template<typename R, class ObjectType>
class CGenericMethod_ : public CMethodBase
{
public:
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CGenericMethod_);

	CGenericMethod_(R(ObjectType::*methodPtr)(void), 
		const char* className, const char* propertyName) :	CMethodBase(propertyName, className), m_methodPtr(methodPtr)
	{
	}

	typedef R (ObjectType::*MethodType_t)();
	CGenericMethod_(R(ObjectType::*methodPtr)(void) const, 
		const char* className, const char* propertyName) :	CMethodBase(propertyName, className), m_methodPtr(MethodType_t(methodPtr))
	{
	}

	CGenericMethod_(const CGenericMethod_& copy) : CMethodBase(copy)
	{
		this->m_methodPtr = copy.m_methodPtr;
	}

	virtual void LoadFromXML(CTagObject* parent, const ISerializableNode& xmlNode)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(xmlNode);
	}

	virtual void SaveToXML(const CTagObject* parent, ISerializableNode& xmlNode)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(xmlNode);
	}

	virtual void GetUiInfo(CTagTypeDescriptor::TypesMap_t* types, const CTagObject* parent, const XmlNodeRef& xmlNode)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(xmlNode);

		XmlNodeRef memberNode = xmlNode;
		if (types == NULL)
		{
			memberNode = xmlNode->newChild("Method");
			memberNode->setAttr("Name", this->m_propertyName);
			memberNode->setAttr("DisplayName", this->GetDisplayName());
			memberNode->setAttr("Desc", this->GetDesc());

			if (this->m_flag & CMethodBase::KMETHOD_NAMEDEVENT)
			{
				memberNode->setAttr("Flag", "namedevent");
			}
			if (this->m_classFullName)
			{
				memberNode->setAttr("Class", this->m_classFullName);
			}
			if (m_bStatic)
			{
				memberNode->setAttr("Static", "true");
			}
			if (this->IsActionMethodOnly())
			{
				memberNode->setAttr("IsActionMethodOnly", "true");
			}

			//const char* pReturn = GetClassTypeName((R*)0);
			//memberNode->setAttr("ReturnType", pReturn);
			behaviac::string returnTypeStr = ::GetTypeDescString<R>();
			memberNode->setAttr("ReturnType", returnTypeStr.c_str());
		}

		typedef PARAM_BASETYPE(R)	ReturnBaseType;
		UserTypeInfoExport<ReturnBaseType>::Export(types, true, memberNode);
	}

	virtual void vCall(const CTagObject* parent)
	{
		(((ObjectType*)parent)->*this->m_methodPtr)();
	}

	virtual int GetParams()
	{
		return 0;
	}

	virtual behaviac::string GetParamTypeName(uint32_t idx)
	{
		BEHAVIAC_UNUSED_VAR(idx);

		return behaviac::string();
	}

protected:
	R(ObjectType::*m_methodPtr)(void);
};


template<typename R, class ObjectType>
class CGenericMethod_R : public CGenericMethod_<R, ObjectType>
{
public:
	CGenericMethod_R(R(ObjectType::*methodPtr)(void), 
		const char* className, const char* propertyName) : CGenericMethod_<R, ObjectType>(methodPtr, className, propertyName)
	{}
	CGenericMethod_R(R(ObjectType::*methodPtr)(void) const, 
		const char* className, const char* propertyName) : CGenericMethod_<R, ObjectType>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod_R()
	{

	}

	virtual behaviac::Property* CreateProperty(const char* defaultValue, bool bConst) const
	{
		behaviac::Property* pProperty = behaviac::Property::Creator<R>(defaultValue, 0, bConst);

		return pProperty;
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod_R(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (CGenericMethod_<R, ObjectType>::m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				bHandled = pNw->SendRemoteEvent(this->m_netRole, nameTemp.c_str());
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)();

			if (this->m_return)
			{
				*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
			}
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
		BEHAVIAC_UNUSED_VAR(params);

		R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)();

		if (this->m_return)
		{
			*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
		}	
	}
#endif//#if BEHAVIAC_ENABLE_NETWORKD
	virtual int vRun(const CTagObject* parent, behaviac::IAsyncValue& returnResult)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(returnResult);
		BEHAVIAC_ASSERT(0);
		return 0;
	}
};

template<typename R, class ObjectType>
class CGenericMethod : public CGenericMethod_R<R, ObjectType>
{
public:
	CGenericMethod(R(ObjectType::*methodPtr)(void), 
		const char* className, const char* propertyName) : CGenericMethod_R<R, ObjectType>(methodPtr, className, propertyName)
	{}
	CGenericMethod(R(ObjectType::*methodPtr)(void) const, 
		const char* className, const char* propertyName) : CGenericMethod_R<R, ObjectType>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod()
	{

	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod(*this);
	}
};

template<class ObjectType>
class CGenericMethod<void, ObjectType> : public CGenericMethod_<void, ObjectType>
{
public:
	CGenericMethod(void (ObjectType::*methodPtr)(void), 
		const char* className, const char* propertyName) : CGenericMethod_<void, ObjectType>(methodPtr, className, propertyName)
	{}

	CGenericMethod(void (ObjectType::*methodPtr)(void) const, 
		const char* className, const char* propertyName) : CGenericMethod_<void, ObjectType>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod()
	{

	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				bHandled = pNw->SendRemoteEvent(this->m_netRole, nameTemp.c_str());
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			(((ObjectType*)parent)->*this->m_methodPtr)();
		}
	}
#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
		BEHAVIAC_UNUSED_VAR(params);

		(((ObjectType*)parent)->*this->m_methodPtr)();
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};

/////////////////////////////////////////////////////////
////////////////     CGenericMethod1_     ////////////////
/////////////////////////////////////////////////////////
template<typename StoredType, typename BaseType, bool bAgent>
struct DefaulParamSetValueSelector
{
	static void SetValue(ParamVariable<StoredType>& p, const DefaultParam_t& defaultParam)
	{
		const StoredType& value = defaultParam.GetValue<BaseType>();
		p.SetValue(value);
	}
};

template<typename StoredType, typename BaseType>
struct DefaulParamSetValueSelector < StoredType, BaseType, true >
{
	static void SetValue(ParamVariable<StoredType>& p, const DefaultParam_t& defaultParam)
	{
	}
};

template<typename R, class ObjectType, class ParamType>
class CGenericMethod1_ : public CMethodBase
{
public:
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CGenericMethod1_);

	typedef PARAM_BASETYPE(ParamType)								ParamBaseType;
	typedef PARAM_POINTERTYPE(ParamType)							ParamPointerType;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType>::Result, VALUE_TYPE(ParamType), ParamBaseType>::Result StoredType;

	CGenericMethod1_(R(ObjectType::*methodPtr)(ParamType), const char* className, const char* propertyName) :
		CMethodBase(propertyName, className), m_methodPtr(methodPtr), m_paramRangeValid(false), m_param()
	{
	}

	typedef R (ObjectType::*MethodType_t)(ParamType);

	CGenericMethod1_(R(ObjectType::*methodPtr)(ParamType) const, const char* className, const char* propertyName) :
		CMethodBase(propertyName, className), m_methodPtr(MethodType_t(methodPtr)), m_paramRangeValid(false), m_param()
	{
	}

	CGenericMethod1_(const CGenericMethod1_& copy) : CMethodBase(copy)
	{
		this->m_methodPtr = copy.m_methodPtr;

		this->m_paramDisplayName = copy.m_paramDisplayName;

		this->m_param = copy.m_param;
		this->m_paramRangeValid = copy.m_paramRangeValid;
	}


	virtual void LoadFromXML(CTagObject* parent, const ISerializableNode& xmlNode)
	{
		this->m_param.LoadFromXML(parent, xmlNode, "param1");
	}

	virtual void SaveToXML(const CTagObject* parent, ISerializableNode& xmlNode)
	{
		this->m_param.SaveToXML(parent, xmlNode, "param1");
	}

	virtual void GetUiInfo(CTagTypeDescriptor::TypesMap_t* types, const CTagObject* parent, const XmlNodeRef& xmlNode)
	{
		BEHAVIAC_UNUSED_VAR(parent);

		XmlNodeRef memberNode = xmlNode;
		if (types == NULL)
		{
			memberNode = xmlNode->newChild("Method");
			memberNode->setAttr("Name", this->m_propertyName);
			memberNode->setAttr("DisplayName", this->GetDisplayName());
			memberNode->setAttr("Desc", this->GetDesc());

			if (this->m_flag & CMethodBase::KMETHOD_NAMEDEVENT)
			{
				memberNode->setAttr("Flag", "namedevent");
			}
			if (this->m_classFullName)
			{
				memberNode->setAttr("Class", this->m_classFullName);
			}
			if (m_bStatic)
			{
				memberNode->setAttr("Static", "true");
			}
			if (this->IsActionMethodOnly())
			{
				memberNode->setAttr("IsActionMethodOnly", "true");
			}

			//const char* returnTypeStr = GetClassTypeName((R*)0);
			//memberNode->setAttr("ReturnType", returnTypeStr);
			behaviac::string returnTypeStr = ::GetTypeDescString<R>();
			memberNode->setAttr("ReturnType", returnTypeStr.c_str());
		}

		UserTypeInfoExport<R>::Export(types, true, memberNode);

		XmlNodeRef paramNode = memberNode;
		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName);
			paramNode->setAttr("Desc", m_paramDesc);

			behaviac::string typeStr = ::GetTypeDescString<ParamType>();
			paramNode->setAttr("Type", typeStr.c_str());

			if (this->m_param.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param.GetValue());
			}
			if (m_paramRangeValid)
			{
				paramNode->setAttr("RangeMin", m_min);
				paramNode->setAttr("RangeMax", m_max);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType, behaviac::Meta::IsEnum<ParamBaseType>::Result>::GetUiInfo(types, paramNode);
	}

	virtual CMethodBase& PARAM_DISPLAYNAME(const wchar_t* paramDisplayName)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);
		m_paramDisplayName = paramDisplayName;

		return *this;
	}

	virtual CMethodBase& PARAM_DESC(const wchar_t* paramDesc)
	{
		BEHAVIAC_UNUSED_VAR(paramDesc);

		m_paramDesc = paramDesc;
		return *this;
	}

	virtual CMethodBase& PARAM_DISPLAY_INFO(const wchar_t* paramDisplayName, const wchar_t* paramDesc = 0, const DefaultParam_t& defaultParam = DefaultParam_t(), float rangeMin = CMETHODBASE_RANGE_MIN_DEFAULT, float rangeMax = CMETHODBASE_RANGE_MAX_DEFAULT)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);
		BEHAVIAC_UNUSED_VAR(paramDesc);
		BEHAVIAC_UNUSED_VAR(defaultParam);
		BEHAVIAC_UNUSED_VAR(rangeMin);
		BEHAVIAC_UNUSED_VAR(rangeMax);


		m_paramDisplayName = paramDisplayName;
		m_paramDesc = (paramDesc == 0 ?  m_paramDisplayName : paramDesc);

		if (defaultParam.IsValid())
		{
			DefaulParamSetValueSelector<StoredType, ParamBaseType, behaviac::Meta::IsAgent<ParamType>::Result>::SetValue(this->m_param, defaultParam);
		}

		int typeId = GetClassTypeNumberId<ParamBaseType>();
		if (IsNumberClassTypeNumberId(typeId))
		{
			BEHAVIAC_ASSERT(rangeMin <= rangeMax);
			this->m_paramRangeValid = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
			this->m_min = rangeMin;
			this->m_max = rangeMax;
		}

		return *this;
	}

	virtual int GetParams()
	{
		return 1;
	}

	virtual behaviac::string GetParamTypeName(uint32_t idx)
	{
		switch (idx)
		{
		case 0:
			{
				behaviac::string typeStr = ::GetTypeDescString<ParamType>();
				return typeStr;
			}

		default:
			return "";
		}
	}

	virtual void vCall(const CTagObject* parent, const void* param1)
	{
		(((ObjectType*)parent)->*this->m_methodPtr)(*(ParamPointerType)param1);
	}

protected:
	R(ObjectType::*m_methodPtr)(ParamType);

	behaviac::wstring					m_paramDisplayName;
	behaviac::wstring					m_paramDesc;

	float								m_min, m_max;
	bool								m_paramRangeValid;
	ParamVariable<StoredType>			m_param;
};


template<typename R, class ObjectType, class ParamType>
class CGenericMethod1_R : public CGenericMethod1_<R, ObjectType, ParamType>
{
public:
	typedef typename CGenericMethod1_<R, ObjectType, ParamType>::ParamBaseType ParamBaseType;

	CGenericMethod1_R(R(ObjectType::*methodPtr)(ParamType), 
		const char* className, const char* propertyName) :	CGenericMethod1_<R, ObjectType, ParamType>(methodPtr, className, propertyName)
	{}

	CGenericMethod1_R(R(ObjectType::*methodPtr)(ParamType) const, 
		const char* className, const char* propertyName) :	CGenericMethod1_<R, ObjectType, ParamType>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod1_R()
	{
	}

	virtual behaviac::Property* CreateProperty(const char* defaultValue, bool bConst) const
	{
		behaviac::Property* pProperty = behaviac::Property::Creator<R>(defaultValue, 0, bConst);

		return pProperty;
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod1_R(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const ParamBaseType& v = this->m_param.GetValue(parent, parHolder);
				bHandled = pNw->SendRemoteEvent<ParamType>(CGenericMethod1_<R, ObjectType, ParamType>::m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType))v);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const ParamBaseType& v = this->m_param.GetValue(parent, parHolder);

			R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)((PARAM_CALLEDTYPE(ParamType))v);

			CGenericMethod1_<R, ObjectType, ParamType>::m_param.SetVariableRegistry(parent, v);

			if (this->m_return)
			{
				*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
			}
		}
	}
#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 1);

		PARAM_BASETYPE(ParamType) p;
		params[0]->GetValue(p);

		R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)((PARAM_CALLEDTYPE(ParamType))p);

		if (this->m_return)
		{
			*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
		}
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
	virtual int vRun(const CTagObject* parent, behaviac::IAsyncValue& returnResult)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(returnResult);
		BEHAVIAC_ASSERT(0);
		return 0;
	}
};

template<typename R, class ObjectType, class ParamType>
class CGenericMethod1 : public CGenericMethod1_R<R, ObjectType, ParamType>
{
public:
	CGenericMethod1(R(ObjectType::*methodPtr)(ParamType), 
		const char* className, const char* propertyName) :	CGenericMethod1_R<R, ObjectType, ParamType>(methodPtr, className, propertyName)
	{}

	CGenericMethod1(R(ObjectType::*methodPtr)(ParamType) const, 
		const char* className, const char* propertyName) :	CGenericMethod1_R<R, ObjectType, ParamType>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod1()
	{

	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod1(*this);
	}
};

template<class ObjectType, class ParamType>
class CGenericMethod1<void, ObjectType, ParamType> : public CGenericMethod1_<void, ObjectType, ParamType>
{
public:
	typedef typename CGenericMethod1_<void, ObjectType, ParamType>::StoredType StoredType;
	typedef typename CGenericMethod1_<void, ObjectType, ParamType>::ParamBaseType ParamBaseType;

	CGenericMethod1(void (ObjectType::*methodPtr)(ParamType), 
		const char* className, const char* propertyName) :
	CGenericMethod1_<void, ObjectType, ParamType>(methodPtr, className, propertyName)
	{}
	CGenericMethod1(void (ObjectType::*methodPtr)(ParamType) const, 
		const char* className, const char* propertyName) :
	CGenericMethod1_<void, ObjectType, ParamType>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod1()
	{
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod1(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const ParamBaseType& v = this->m_param.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType))v);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType& v = this->m_param.GetValue(parent, parHolder);
			(((ObjectType*)parent)->*this->m_methodPtr)((PARAM_CALLEDTYPE(ParamType))v);

			this->m_param.SetVariableRegistry(parent, v);
		}
	}
#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_ASSERT(params.size() == 1);

		PARAM_BASETYPE(ParamType) p;
		params[0]->GetValue(p);

		(((ObjectType*)parent)->*this->m_methodPtr)((PARAM_CALLEDTYPE(ParamType))p);

		this->m_param.SetVariableRegistry(parHolder, p);
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};

/////////////////////////////////////////////////////////
////////////////     CGenericMethod2_     ////////////////
/////////////////////////////////////////////////////////

template<typename R, class ObjectType, class ParamType1, class ParamType2>
class CGenericMethod2_ : public CMethodBase
{
public:
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CGenericMethod2_);

	typedef PARAM_BASETYPE(ParamType1)				ParamBaseType1;
	typedef PARAM_BASETYPE(ParamType2)				ParamBaseType2;
	typedef PARAM_POINTERTYPE(ParamType1)			ParamPointerType1;
	typedef PARAM_POINTERTYPE(ParamType2)			ParamPointerType2;

	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType1>::Result, VALUE_TYPE(ParamType1), ParamBaseType1>::Result StoredType1;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType2>::Result, VALUE_TYPE(ParamType2), ParamBaseType2>::Result StoredType2;

	CGenericMethod2_(R(ObjectType::*methodPtr)(ParamType1, ParamType2), const char* className, const char* propertyName) :
		CMethodBase(propertyName, className), m_methodPtr(methodPtr), 
		m_paramRangeValid1(false), m_paramRangeValid2(false),
		m_param1(), m_param2()
	{
	}

	typedef R (ObjectType::*MethodType_t)(ParamType1, ParamType2);

	CGenericMethod2_(R(ObjectType::*methodPtr)(ParamType1, ParamType2) const, const char* className, const char* propertyName) :
	CMethodBase(propertyName, className), m_methodPtr(MethodType_t(methodPtr)), 
		m_paramRangeValid1(false), m_paramRangeValid2(false),
		m_param1(), m_param2()
	{
	}

	CGenericMethod2_(const CGenericMethod2_& copy) : CMethodBase(copy)
	{
		this->m_methodPtr = copy.m_methodPtr;

		this->m_paramDisplayName1 = copy.m_paramDisplayName1;
		this->m_paramDisplayName2 = copy.m_paramDisplayName2;

		this->m_param1 = copy.m_param1;
		this->m_param2 = copy.m_param2;
		this->m_paramRangeValid1 = copy.m_paramRangeValid1;
		this->m_paramRangeValid2 = copy.m_paramRangeValid2;
	}

	virtual void LoadFromXML(CTagObject* parent, const ISerializableNode& xmlNode)
	{
		this->m_param1.LoadFromXML(parent, xmlNode, "param1");
		this->m_param2.LoadFromXML(parent, xmlNode, "param2");
	}

	virtual void SaveToXML(const CTagObject* parent, ISerializableNode& xmlNode)
	{
		this->m_param1.SaveToXML(parent, xmlNode, "param1");
		this->m_param2.SaveToXML(parent, xmlNode, "param2");
	}

	virtual void GetUiInfo(CTagTypeDescriptor::TypesMap_t* types, const CTagObject* parent, const XmlNodeRef& xmlNode)
	{
		BEHAVIAC_UNUSED_VAR(parent);

		XmlNodeRef memberNode = xmlNode;
		if (types == NULL)
		{
			memberNode = xmlNode->newChild("Method");
			memberNode->setAttr("Name", this->m_propertyName);
			memberNode->setAttr("DisplayName", this->GetDisplayName());
			memberNode->setAttr("Desc", this->GetDesc());

			if (this->m_flag & CMethodBase::KMETHOD_NAMEDEVENT)
			{
				memberNode->setAttr("Flag", "namedevent");
			}
			if (this->m_classFullName)
			{
				memberNode->setAttr("Class", this->m_classFullName);
			}
			if (m_bStatic)
			{
				memberNode->setAttr("Static", "true");
			}
			if (this->IsActionMethodOnly())
			{
				memberNode->setAttr("IsActionMethodOnly", "true");
			}

			//const char* pReturn = GetClassTypeName((R*)0);
			//memberNode->setAttr("ReturnType", pReturn);
			behaviac::string returnTypeStr = ::GetTypeDescString<R>();
			memberNode->setAttr("ReturnType", returnTypeStr.c_str());
		}

		UserTypeInfoExport<R>::Export(types, true, memberNode);

		XmlNodeRef paramNode = memberNode;
		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName1);
			paramNode->setAttr("Desc", m_paramDesc1);

			behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
			paramNode->setAttr("Type", typeStr1.c_str());

			if (this->m_param1.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param1.GetValue());
			}
			if (m_paramRangeValid1)
			{
				paramNode->setAttr("RangeMin", m_min1);
				paramNode->setAttr("RangeMax", m_max1);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType1, behaviac::Meta::IsEnum<ParamBaseType1>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName2);
			paramNode->setAttr("Desc", m_paramDesc2);

			behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
			paramNode->setAttr("Type", typeStr2.c_str());

			if (this->m_param2.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param2.GetValue());
			}
			if (m_paramRangeValid2)
			{
				paramNode->setAttr("RangeMin", m_min2);
				paramNode->setAttr("RangeMax", m_max2);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType2, behaviac::Meta::IsEnum<ParamBaseType2>::Result>::GetUiInfo(types, paramNode);
	}

	virtual CMethodBase& PARAM_DISPLAYNAME(const wchar_t* paramDisplayName)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DESC(const wchar_t* paramDesc)
	{
		BEHAVIAC_UNUSED_VAR(paramDesc);

		if (m_paramDesc1.empty())
		{
			m_paramDesc1 = paramDesc;
		}
		else if (m_paramDesc2.empty())
		{
			m_paramDesc2 = paramDesc;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DISPLAY_INFO(const wchar_t* paramDisplayName, const wchar_t* paramDesc = 0, const DefaultParam_t& defaultParam = DefaultParam_t(), float rangeMin = CMETHODBASE_RANGE_MIN_DEFAULT, float rangeMax = CMETHODBASE_RANGE_MAX_DEFAULT)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);
		BEHAVIAC_UNUSED_VAR(paramDesc);
		BEHAVIAC_UNUSED_VAR(defaultParam);
		BEHAVIAC_UNUSED_VAR(rangeMin);
		BEHAVIAC_UNUSED_VAR(rangeMax);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
			m_paramDesc1 = (paramDesc == 0 ?  m_paramDisplayName1 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType1, ParamBaseType1, behaviac::Meta::IsAgent<ParamType1>::Result>::SetValue(this->m_param1, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType1>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid1 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min1 = rangeMin;
				this->m_max1 = rangeMax;
			}
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
			m_paramDesc2 = (paramDesc == 0 ?  m_paramDisplayName2 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType2, ParamBaseType2, behaviac::Meta::IsAgent<ParamType2>::Result>::SetValue(this->m_param2, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType2>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid2 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min2 = rangeMin;
				this->m_max2 = rangeMax;
			}
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DEFAULTVALUE(int paramIndex, const DefaultParam_t& defaultParam)
	{
		if (paramIndex == 0)
		{
			DefaulParamSetValueSelector<StoredType1, ParamBaseType1, behaviac::Meta::IsAgent<ParamType1>::Result>::SetValue(this->m_param1, defaultParam);
		}
		else if (paramIndex == 1)
		{
			DefaulParamSetValueSelector<StoredType2, ParamBaseType2, behaviac::Meta::IsAgent<ParamType2>::Result>::SetValue(this->m_param2, defaultParam);
		}
		else
		{
			BEHAVIAC_ASSERT(0, "not supported param");
		}

		return *this;
	}

	virtual int GetParams()
	{
		return 2;
	}

	virtual behaviac::string GetParamTypeName(uint32_t idx)
	{
		switch (idx)
		{
		case 0:
			{
				behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
				return typeStr1;
			}

		case 1:
			{
				behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
				return typeStr2;
			}

		default:
			return "";
		}
	}

	virtual void vCall(const CTagObject* parent, const void* param1, const void* param2)
	{
		(((ObjectType*)parent)->*this->m_methodPtr)(*((ParamPointerType1)param1), *((ParamPointerType2)param2));
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod2_(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1, 
				(PARAM_CALLEDTYPE(ParamType2))v2);

			this->m_param1.SetVariableRegistry(parent, v1);
			this->m_param2.SetVariableRegistry(parent, v2);
		}
	}
#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 2);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);

		(((ObjectType*)parent)->*this->m_methodPtr)((PARAM_CALLEDTYPE(ParamType1))p1, (PARAM_CALLEDTYPE(ParamType2))p2);	
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
protected:
	R(ObjectType::*m_methodPtr)(ParamType1, ParamType2);

	behaviac::wstring				m_paramDisplayName1;
	behaviac::wstring				m_paramDesc1;
	behaviac::wstring				m_paramDisplayName2;
	behaviac::wstring				m_paramDesc2;

	bool							m_paramRangeValid1;
	float							m_min1, m_max1;
	bool							m_paramRangeValid2;
	float							m_min2, m_max2;

	ParamVariable<StoredType1>		m_param1;
	ParamVariable<StoredType2>		m_param2;
};


template<typename R, class ObjectType, class ParamType1, class ParamType2>
class CGenericMethod2 : public CGenericMethod2_<R, ObjectType, ParamType1, ParamType2>
{
public:
	typedef typename CGenericMethod2_<R, ObjectType, ParamType1, ParamType2>::StoredType1 StoredType1;
	typedef typename CGenericMethod2_<R, ObjectType, ParamType1, ParamType2>::StoredType2 StoredType2;
	typedef typename CGenericMethod2_<R, ObjectType, ParamType1, ParamType2>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod2_<R, ObjectType, ParamType1, ParamType2>::ParamBaseType2 ParamBaseType2;

	CGenericMethod2(R(ObjectType::*methodPtr)(ParamType1, ParamType2), 
		const char* className, const char* propertyName
		) :
	CGenericMethod2_<R, ObjectType, ParamType1, ParamType2>(methodPtr, className, propertyName)
	{}

	CGenericMethod2(R(ObjectType::*methodPtr)(ParamType1, ParamType2) const, 
		const char* className, const char* propertyName
		) :
	CGenericMethod2_<R, ObjectType, ParamType1, ParamType2>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod2()
	{
	}

	virtual behaviac::Property* CreateProperty(const char* defaultValue, bool bConst) const
	{
		behaviac::Property* pProperty = behaviac::Property::Creator<R>(defaultValue, 0, bConst);

		return pProperty;
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod2(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);

			R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1, 
				(PARAM_CALLEDTYPE(ParamType2))v2);

			this->m_param1.SetVariableRegistry(parent, v1);
			this->m_param2.SetVariableRegistry(parent, v2);

			if (this->m_return)
			{
				*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
			}
		}
	}
#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 2);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);

		R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2);

		if (this->m_return)
		{
			*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
		}
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};

template<class ObjectType, class ParamType1, class ParamType2>
class CGenericMethod2<void, ObjectType, ParamType1, ParamType2> : public CGenericMethod2_<void, ObjectType, ParamType1, ParamType2>
{
public:
	typedef typename CGenericMethod2_<void, ObjectType, ParamType1, ParamType2>::StoredType1 StoredType1;
	typedef typename CGenericMethod2_<void, ObjectType, ParamType1, ParamType2>::StoredType2 StoredType2;
	typedef typename CGenericMethod2_<void, ObjectType, ParamType1, ParamType2>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod2_<void, ObjectType, ParamType1, ParamType2>::ParamBaseType2 ParamBaseType2;

	CGenericMethod2(void (ObjectType::*methodPtr)(ParamType1, ParamType2), 
		const char* className, const char* propertyName
		) :
	CGenericMethod2_<void, ObjectType, ParamType1, ParamType2>(methodPtr, className, propertyName)
	{}

	CGenericMethod2(void (ObjectType::*methodPtr)(ParamType1, ParamType2) const, 
		const char* className, const char* propertyName
		) :
	CGenericMethod2_<void, ObjectType, ParamType1, ParamType2>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod2()
	{
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod2(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1, 
				(PARAM_CALLEDTYPE(ParamType2))v2);

			this->m_param1.SetVariableRegistry(parent, v1);
			this->m_param2.SetVariableRegistry(parent, v2);
		}
	}
#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 2);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);

		(((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2);
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};


/////////////////////////////////////////////////////////
////////////////     CGenericMethod3_     ////////////////
/////////////////////////////////////////////////////////

template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3>
class CGenericMethod3_ : public CMethodBase
{
public:
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CGenericMethod3_);

	typedef PARAM_BASETYPE(ParamType1)				ParamBaseType1;
	typedef PARAM_BASETYPE(ParamType2)				ParamBaseType2;
	typedef PARAM_BASETYPE(ParamType3)				ParamBaseType3;
	typedef PARAM_POINTERTYPE(ParamType1)			ParamPointerType1;
	typedef PARAM_POINTERTYPE(ParamType2)			ParamPointerType2;
	typedef PARAM_POINTERTYPE(ParamType3)			ParamPointerType3;

	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType1>::Result, VALUE_TYPE(ParamType1), ParamBaseType1>::Result StoredType1;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType2>::Result, VALUE_TYPE(ParamType2), ParamBaseType2>::Result StoredType2;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType3>::Result, VALUE_TYPE(ParamType3), ParamBaseType3>::Result StoredType3;

	CGenericMethod3_(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3), const char* className, const char* propertyName) :
		CMethodBase(propertyName, className), m_methodPtr(methodPtr),
		m_paramRangeValid1(false), m_paramRangeValid2(false), m_paramRangeValid3(false),
		m_param1(), m_param2(), m_param3()
	{
	}

	typedef R (ObjectType::*MethodType_t)(ParamType1, ParamType2, ParamType3);
	CGenericMethod3_(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3) const, const char* className, const char* propertyName) :
	CMethodBase(propertyName, className), m_methodPtr(methodPtr), 
		m_paramRangeValid1(false), m_paramRangeValid2(false), m_paramRangeValid3(false),
		m_param1(), m_param2(), m_param3()
	{
	}

	CGenericMethod3_(const CGenericMethod3_& copy) : CMethodBase(copy)
	{
		this->m_methodPtr = copy.m_methodPtr;

		this->m_paramDisplayName1 = copy.m_paramDisplayName1;
		this->m_paramDisplayName2 = copy.m_paramDisplayName2;
		this->m_paramDisplayName3 = copy.m_paramDisplayName3;

		this->m_param1 = copy.m_param1;
		this->m_param2 = copy.m_param2;
		this->m_param3 = copy.m_param3;
		this->m_paramRangeValid1 = copy.m_paramRangeValid1;
		this->m_paramRangeValid2 = copy.m_paramRangeValid2;
		this->m_paramRangeValid3 = copy.m_paramRangeValid3;
	}

	virtual void LoadFromXML(CTagObject* parent, const ISerializableNode& xmlNode)
	{
		this->m_param1.LoadFromXML(parent, xmlNode, "param1");
		this->m_param2.LoadFromXML(parent, xmlNode, "param2");
		this->m_param3.LoadFromXML(parent, xmlNode, "param3");
	}

	virtual void SaveToXML(const CTagObject* parent, ISerializableNode& xmlNode)
	{
		this->m_param1.SaveToXML(parent, xmlNode, "param1");
		this->m_param2.SaveToXML(parent, xmlNode, "param2");
		this->m_param3.SaveToXML(parent, xmlNode, "param3");
	}

	virtual void GetUiInfo(CTagTypeDescriptor::TypesMap_t* types, const CTagObject* parent, const XmlNodeRef& xmlNode)
	{
		BEHAVIAC_UNUSED_VAR(parent);

		XmlNodeRef memberNode = xmlNode;
		if (types == NULL)
		{
			memberNode = xmlNode->newChild("Method");
			memberNode->setAttr("Name", this->m_propertyName);
			memberNode->setAttr("DisplayName", this->GetDisplayName());
			memberNode->setAttr("Desc", this->GetDesc());

			if (this->m_flag & CMethodBase::KMETHOD_NAMEDEVENT)
			{
				memberNode->setAttr("Flag", "namedevent");
			}
			if (this->m_classFullName)
			{
				memberNode->setAttr("Class", this->m_classFullName);
			}
			if (m_bStatic)
			{
				memberNode->setAttr("Static", "true");
			}
			if (this->IsActionMethodOnly())
			{
				memberNode->setAttr("IsActionMethodOnly", "true");
			}

			//const char* pReturn = GetClassTypeName((R*)0);
			//memberNode->setAttr("ReturnType", pReturn);
			behaviac::string returnTypeStr = ::GetTypeDescString<R>();
			memberNode->setAttr("ReturnType", returnTypeStr.c_str());
		}

		UserTypeInfoExport<R>::Export(types, true, memberNode);

		XmlNodeRef paramNode = memberNode;
		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName1);
			paramNode->setAttr("Desc", m_paramDesc1);

			behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
			paramNode->setAttr("Type", typeStr1.c_str());
			if (this->m_param1.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param1.GetValue());
			}
			if (m_paramRangeValid1)
			{
				paramNode->setAttr("RangeMin", m_min1);
				paramNode->setAttr("RangeMax", m_max1);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType1, behaviac::Meta::IsEnum<ParamBaseType1>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName2);
			paramNode->setAttr("Desc", m_paramDesc2);

			behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
			paramNode->setAttr("Type", typeStr2.c_str());
			if (this->m_param2.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param2.GetValue());
			}
			if (m_paramRangeValid2)
			{
				paramNode->setAttr("RangeMin", m_min2);
				paramNode->setAttr("RangeMax", m_max2);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType2, behaviac::Meta::IsEnum<ParamBaseType2>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName3);
			paramNode->setAttr("Desc", m_paramDesc3);

			behaviac::string typeStr3 = ::GetTypeDescString<ParamType3>();
			paramNode->setAttr("Type", typeStr3.c_str());
			if (this->m_param3.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param3.GetValue());
			}
			if (m_paramRangeValid3)
			{
				paramNode->setAttr("RangeMin", m_min3);
				paramNode->setAttr("RangeMax", m_max3);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType3, behaviac::Meta::IsEnum<ParamBaseType3>::Result>::GetUiInfo(types, paramNode);
	}

	virtual CMethodBase& PARAM_DISPLAYNAME(const wchar_t* paramDisplayName)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
		}
		else if (m_paramDisplayName3.empty())
		{
			m_paramDisplayName3 = paramDisplayName;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DESC(const wchar_t* paramDesc)
	{
		BEHAVIAC_UNUSED_VAR(paramDesc);

		if (m_paramDesc1.empty())
		{
			m_paramDesc1 = paramDesc;
		}
		else if (m_paramDesc2.empty())
		{
			m_paramDesc2 = paramDesc;
		}
		else if (m_paramDesc3.empty())
		{
			m_paramDesc3 = paramDesc;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DISPLAY_INFO(const wchar_t* paramDisplayName, const wchar_t* paramDesc = 0, const DefaultParam_t& defaultParam = DefaultParam_t(), float rangeMin = CMETHODBASE_RANGE_MIN_DEFAULT, float rangeMax = CMETHODBASE_RANGE_MAX_DEFAULT)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);
		BEHAVIAC_UNUSED_VAR(paramDesc);
		BEHAVIAC_UNUSED_VAR(defaultParam);
		BEHAVIAC_UNUSED_VAR(rangeMin);
		BEHAVIAC_UNUSED_VAR(rangeMax);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
			m_paramDesc1 = (paramDesc == 0 ?  m_paramDisplayName1 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType1, ParamBaseType1, behaviac::Meta::IsAgent<ParamType1>::Result>::SetValue(this->m_param1, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType1>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid1 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min1 = rangeMin;
				this->m_max1 = rangeMax;
			}
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
			m_paramDesc2 = (paramDesc == 0 ?  m_paramDisplayName2 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType2, ParamBaseType2, behaviac::Meta::IsAgent<ParamType2>::Result>::SetValue(this->m_param2, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType2>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid2 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min2 = rangeMin;
				this->m_max2 = rangeMax;
			}
		}
		else if (m_paramDisplayName3.empty())
		{
			m_paramDisplayName3 = paramDisplayName;
			m_paramDesc3 = (paramDesc == 0 ?  m_paramDisplayName3 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType3, ParamBaseType3, behaviac::Meta::IsAgent<ParamType3>::Result>::SetValue(this->m_param3, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType3>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid3 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min3 = rangeMin;
				this->m_max3 = rangeMax;
			}
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual int GetParams()
	{
		return 3;
	}

	virtual behaviac::string GetParamTypeName(uint32_t idx)
	{
		switch (idx)
		{
		case 0:
			{
				behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
				return typeStr1;
			}

		case 1:
			{
				behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
				return typeStr2;
			}

		case 2:
			{
				behaviac::string typeStr3 = ::GetTypeDescString<ParamType3>();
				return typeStr3;
			}

		default:
			return "";
		}
	}

	virtual void vCall(const CTagObject* parent, const void* param1, const void* param2, const void* param3)
	{
		(((ObjectType*)parent)->*this->m_methodPtr)(*(ParamPointerType1)param1, *(ParamPointerType2)param2, *(ParamPointerType3)param3);
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod3_(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1, 
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3);

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 3);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);

		(((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3);
	}
#endif//BEHAVIAC_ENABLE_NETWORKD

protected:
	R(ObjectType::*m_methodPtr)(ParamType1, ParamType2, ParamType3);

	behaviac::wstring				m_paramDisplayName1;
	behaviac::wstring				m_paramDesc1;
	behaviac::wstring				m_paramDisplayName2;
	behaviac::wstring				m_paramDesc2;
	behaviac::wstring				m_paramDisplayName3;
	behaviac::wstring				m_paramDesc3;

	bool							m_paramRangeValid1;
	float							m_min1, m_max1;
	bool							m_paramRangeValid2;
	float							m_min2, m_max2;
	bool							m_paramRangeValid3;
	float							m_min3, m_max3;

	ParamVariable<StoredType1>		m_param1;
	ParamVariable<StoredType2>		m_param2;
	ParamVariable<StoredType3>		m_param3;
};

template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3>
class CGenericMethod3 : public CGenericMethod3_<R, ObjectType, ParamType1, ParamType2, ParamType3>
{
public:
	typedef typename CGenericMethod3_<R, ObjectType, ParamType1, ParamType2, ParamType3>::StoredType1 StoredType1;
	typedef typename CGenericMethod3_<R, ObjectType, ParamType1, ParamType2, ParamType3>::StoredType2 StoredType2;
	typedef typename CGenericMethod3_<R, ObjectType, ParamType1, ParamType2, ParamType3>::StoredType3 StoredType3;
	typedef typename CGenericMethod3_<R, ObjectType, ParamType1, ParamType2, ParamType3>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod3_<R, ObjectType, ParamType1, ParamType2, ParamType3>::ParamBaseType2 ParamBaseType2;
	typedef typename CGenericMethod3_<R, ObjectType, ParamType1, ParamType2, ParamType3>::ParamBaseType3 ParamBaseType3;

	CGenericMethod3(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3),
		const char* className, const char* propertyName
		) :
	CGenericMethod3_<R, ObjectType, ParamType1, ParamType2, ParamType3>(methodPtr, className, propertyName)
	{}

	CGenericMethod3(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3) const,
		const char* className, const char* propertyName
		) :
	CGenericMethod3_<R, ObjectType, ParamType1, ParamType2, ParamType3>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod3()
	{
	}

	virtual behaviac::Property* CreateProperty(const char* defaultValue, bool bConst) const
	{
		behaviac::Property* pProperty = behaviac::Property::Creator<R>(defaultValue, 0, bConst);

		return pProperty;
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod3(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);

			R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1, 
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3);

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);

			if (this->m_return)
			{
				*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
			}
		}
	}
#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 3);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);

		R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3);

		if (this->m_return)
		{
			*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
		}
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};

template<class ObjectType, class ParamType1, class ParamType2, class ParamType3>
class CGenericMethod3<void, ObjectType, ParamType1, ParamType2, ParamType3> : public CGenericMethod3_<void, ObjectType, ParamType1, ParamType2, ParamType3>
{
public:
	typedef typename CGenericMethod3_<void, ObjectType, ParamType1, ParamType2, ParamType3>::StoredType1 StoredType1;
	typedef typename CGenericMethod3_<void, ObjectType, ParamType1, ParamType2, ParamType3>::StoredType2 StoredType2;
	typedef typename CGenericMethod3_<void, ObjectType, ParamType1, ParamType2, ParamType3>::StoredType3 StoredType3;
	typedef typename CGenericMethod3_<void, ObjectType, ParamType1, ParamType2, ParamType3>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod3_<void, ObjectType, ParamType1, ParamType2, ParamType3>::ParamBaseType2 ParamBaseType2;
	typedef typename CGenericMethod3_<void, ObjectType, ParamType1, ParamType2, ParamType3>::ParamBaseType3 ParamBaseType3;

	CGenericMethod3(void (ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3),
		const char* className, const char* propertyName
		) :
	CGenericMethod3_<void, ObjectType, ParamType1, ParamType2, ParamType3>(methodPtr, className, propertyName)
	{}

	CGenericMethod3(void (ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3) const,
		const char* className, const char* propertyName
		) :
	CGenericMethod3_<void, ObjectType, ParamType1, ParamType2, ParamType3>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod3()
	{
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod3(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1, 
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3);

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 3);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);

		(((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3);
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};


/////////////////////////////////////////////////////////
////////////////     CGenericMethod4_     ///////////////
/////////////////////////////////////////////////////////

template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
class CGenericMethod4_ : public CMethodBase
{
public:
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CGenericMethod4_);

	typedef PARAM_BASETYPE(ParamType1)				ParamBaseType1;
	typedef PARAM_BASETYPE(ParamType2)				ParamBaseType2;
	typedef PARAM_BASETYPE(ParamType3)				ParamBaseType3;
	typedef PARAM_BASETYPE(ParamType4)				ParamBaseType4;

	typedef PARAM_POINTERTYPE(ParamType1)			ParamPointerType1;
	typedef PARAM_POINTERTYPE(ParamType2)			ParamPointerType2;
	typedef PARAM_POINTERTYPE(ParamType3)			ParamPointerType3;
	typedef PARAM_POINTERTYPE(ParamType4)			ParamPointerType4;

	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType1>::Result, VALUE_TYPE(ParamType1), ParamBaseType1>::Result StoredType1;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType2>::Result, VALUE_TYPE(ParamType2), ParamBaseType2>::Result StoredType2;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType3>::Result, VALUE_TYPE(ParamType3), ParamBaseType3>::Result StoredType3;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType4>::Result, VALUE_TYPE(ParamType4), ParamBaseType4>::Result StoredType4;

	CGenericMethod4_(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4), 
		const char* className, const char* propertyName ) :
		CMethodBase(propertyName, className), m_methodPtr(methodPtr),
		m_paramRangeValid1(false), m_paramRangeValid2(false), m_paramRangeValid3(false), m_paramRangeValid4(false),
		m_param1(), m_param2(), m_param3(), m_param4()
	{
	}

	typedef R (ObjectType::*MethodType_t)(ParamType1, ParamType2, ParamType3, ParamType4);

	CGenericMethod4_(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4) const, 
		const char* className, const char* propertyName ) :
		CMethodBase(propertyName, className), m_methodPtr(MethodType_t(methodPtr)),
		m_paramRangeValid1(false), m_paramRangeValid2(false), m_paramRangeValid3(false), m_paramRangeValid4(false),
		m_param1(), m_param2(), m_param3(), m_param4()
	{
	}

	CGenericMethod4_(const CGenericMethod4_& copy) : CMethodBase(copy)
	{
		this->m_methodPtr = copy.m_methodPtr;

		this->m_paramDisplayName1 = copy.m_paramDisplayName1;
		this->m_paramDisplayName2 = copy.m_paramDisplayName2;
		this->m_paramDisplayName3 = copy.m_paramDisplayName3;
		this->m_paramDisplayName4 = copy.m_paramDisplayName4;

		this->m_param1 = copy.m_param1;
		this->m_param2 = copy.m_param2;
		this->m_param3 = copy.m_param3;
		this->m_param4 = copy.m_param4;
		this->m_paramRangeValid1 = copy.m_paramRangeValid1;
		this->m_paramRangeValid2 = copy.m_paramRangeValid2;
		this->m_paramRangeValid3 = copy.m_paramRangeValid3;
		this->m_paramRangeValid4 = copy.m_paramRangeValid4;
	}

	virtual void LoadFromXML(CTagObject* parent, const ISerializableNode& xmlNode)
	{
		BEHAVIAC_UNUSED_VAR(parent);

		this->m_param1.LoadFromXML(parent, xmlNode, "param1");
		this->m_param2.LoadFromXML(parent, xmlNode, "param2");
		this->m_param3.LoadFromXML(parent, xmlNode, "param3");
		this->m_param4.LoadFromXML(parent, xmlNode, "param4");
	}

	virtual void SaveToXML(const CTagObject* parent, ISerializableNode& xmlNode)
	{
		this->m_param1.SaveToXML(parent, xmlNode, "param1");
		this->m_param2.SaveToXML(parent, xmlNode, "param2");
		this->m_param3.SaveToXML(parent, xmlNode, "param3");
		this->m_param4.SaveToXML(parent, xmlNode, "param4");
	}

	virtual void GetUiInfo(CTagTypeDescriptor::TypesMap_t* types, const CTagObject* parent, const XmlNodeRef& xmlNode)
	{
		BEHAVIAC_UNUSED_VAR(parent);

		XmlNodeRef memberNode = xmlNode;
		if (types == NULL)
		{
			memberNode = xmlNode->newChild("Method");
			memberNode->setAttr("Name", this->m_propertyName);
			memberNode->setAttr("DisplayName", this->GetDisplayName());
			memberNode->setAttr("Desc", this->GetDesc());

			if (this->m_flag & CMethodBase::KMETHOD_NAMEDEVENT)
			{
				memberNode->setAttr("Flag", "namedevent");
			}
			if (this->m_classFullName)
			{
				memberNode->setAttr("Class", this->m_classFullName);
			}
			if (m_bStatic)
			{
				memberNode->setAttr("Static", "true");
			}
			if (this->IsActionMethodOnly())
			{
				memberNode->setAttr("IsActionMethodOnly", "true");
			}

			//const char* pReturn = GetClassTypeName((R*)0);
			//memberNode->setAttr("ReturnType", pReturn);
			behaviac::string returnTypeStr = ::GetTypeDescString<R>();
			memberNode->setAttr("ReturnType", returnTypeStr.c_str());
		}

		UserTypeInfoExport<R>::Export(types, true, memberNode);

		XmlNodeRef paramNode = memberNode;
		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName1);
			paramNode->setAttr("Desc", m_paramDesc1);

			behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
			paramNode->setAttr("Type", typeStr1.c_str());
			if (this->m_param1.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param1.GetValue());
			}
			if (m_paramRangeValid1)
			{
				paramNode->setAttr("RangeMin", m_min1);
				paramNode->setAttr("RangeMax", m_max1);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType1, behaviac::Meta::IsEnum<ParamBaseType1>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName2);
			paramNode->setAttr("Desc", m_paramDesc2);

			behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
			paramNode->setAttr("Type", typeStr2.c_str());
			if (this->m_param2.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param2.GetValue());
			}
			if (m_paramRangeValid2)
			{
				paramNode->setAttr("RangeMin", m_min2);
				paramNode->setAttr("RangeMax", m_max2);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType2, behaviac::Meta::IsEnum<ParamBaseType2>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName3);
			paramNode->setAttr("Desc", m_paramDesc3);

			behaviac::string typeStr3 = ::GetTypeDescString<ParamType3>();
			paramNode->setAttr("Type", typeStr3.c_str());
			if (this->m_param3.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param3.GetValue());
			}
			if (m_paramRangeValid3)
			{
				paramNode->setAttr("RangeMin", m_min3);
				paramNode->setAttr("RangeMax", m_max3);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType3, behaviac::Meta::IsEnum<ParamBaseType3>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName4);
			paramNode->setAttr("Desc", m_paramDesc4);

			behaviac::string typeStr4 = ::GetTypeDescString<ParamType4>();
			paramNode->setAttr("Type", typeStr4.c_str());
			if (this->m_param4.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param4.GetValue());
			}
			if (m_paramRangeValid4)
			{
				paramNode->setAttr("RangeMin", m_min4);
				paramNode->setAttr("RangeMax", m_max4);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType4, behaviac::Meta::IsEnum<ParamBaseType4>::Result>::GetUiInfo(types, paramNode);
	}

	virtual CMethodBase& PARAM_DISPLAYNAME(const wchar_t* paramDisplayName)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
		}
		else if (m_paramDisplayName3.empty())
		{
			m_paramDisplayName3 = paramDisplayName;
		}
		else if (m_paramDisplayName4.empty())
		{
			m_paramDisplayName4 = paramDisplayName;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DESC(const wchar_t* paramDesc)
	{
		BEHAVIAC_UNUSED_VAR(paramDesc);

		if (m_paramDesc1.empty())
		{
			m_paramDesc1 = paramDesc;
		}
		else if (m_paramDesc2.empty())
		{
			m_paramDesc2 = paramDesc;
		}
		else if (m_paramDesc3.empty())
		{
			m_paramDesc3 = paramDesc;
		}
		else if (m_paramDesc4.empty())
		{
			m_paramDesc4 = paramDesc;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DISPLAY_INFO(const wchar_t* paramDisplayName, const wchar_t* paramDesc = 0, const DefaultParam_t& defaultParam = DefaultParam_t(), float rangeMin = CMETHODBASE_RANGE_MIN_DEFAULT, float rangeMax = CMETHODBASE_RANGE_MAX_DEFAULT)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);
		BEHAVIAC_UNUSED_VAR(paramDesc);
		BEHAVIAC_UNUSED_VAR(defaultParam);
		BEHAVIAC_UNUSED_VAR(rangeMin);
		BEHAVIAC_UNUSED_VAR(rangeMax);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
			m_paramDesc1 = (paramDesc == 0 ?  m_paramDisplayName1 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType1, ParamBaseType1, behaviac::Meta::IsAgent<ParamType1>::Result>::SetValue(this->m_param1, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType1>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid1 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min1 = rangeMin;
				this->m_max1 = rangeMax;
			}
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
			m_paramDesc2 = (paramDesc == 0 ?  m_paramDisplayName2 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType2, ParamBaseType2, behaviac::Meta::IsAgent<ParamType2>::Result>::SetValue(this->m_param2, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType2>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid2 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min2 = rangeMin;
				this->m_max2 = rangeMax;
			}
		}
		else if (m_paramDisplayName3.empty())
		{
			m_paramDisplayName3 = paramDisplayName;
			m_paramDesc3 = (paramDesc == 0 ?  m_paramDisplayName3 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType3, ParamBaseType3, behaviac::Meta::IsAgent<ParamType3>::Result>::SetValue(this->m_param3, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType3>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid3 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min3 = rangeMin;
				this->m_max3 = rangeMax;
			}
		}
		else if (m_paramDisplayName4.empty())
		{
			m_paramDisplayName4 = paramDisplayName;
			m_paramDesc4 = (paramDesc == 0 ?  m_paramDisplayName4 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType4, ParamBaseType4, behaviac::Meta::IsAgent<ParamType4>::Result>::SetValue(this->m_param4, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType4>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid4 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min4 = rangeMin;
				this->m_max4 = rangeMax;
			}
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual int GetParams()
	{
		return 4;
	}

	virtual behaviac::string GetParamTypeName(uint32_t idx)
	{
		switch (idx)
		{
		case 0:
			{
				behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
				return typeStr1;
			}

		case 1:
			{
				behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
				return typeStr2;
			}

		case 2:
			{
				behaviac::string typeStr3 = ::GetTypeDescString<ParamType3>();
				return typeStr3;
			}

		case 3:
			{
				behaviac::string typeStr4 = ::GetTypeDescString<ParamType4>();
				return typeStr4;
			}

		default:
			return "";
		}
	}

	virtual void vCall(const CTagObject* parent, const void* param1, const void* param2, const void* param3, const void* param4)
	{
		(((ObjectType*)parent)->*this->m_methodPtr)(*(ParamPointerType1)param1, *(ParamPointerType2)param2, *(ParamPointerType3)param3, *(ParamPointerType4)param4);
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod4_(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1, 
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3, 
				(PARAM_CALLEDTYPE(ParamType4))v4);

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 4);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);

		(((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3, 
			(PARAM_CALLEDTYPE(ParamType4))p4);
	}
#endif//BEHAVIAC_ENABLE_NETWORKD

protected:
	R(ObjectType::*m_methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4);

	behaviac::wstring				m_paramDisplayName1;
	behaviac::wstring				m_paramDesc1;
	behaviac::wstring				m_paramDisplayName2;
	behaviac::wstring				m_paramDesc2;
	behaviac::wstring				m_paramDisplayName3;
	behaviac::wstring				m_paramDesc3;
	behaviac::wstring				m_paramDisplayName4;
	behaviac::wstring				m_paramDesc4;

	bool							m_paramRangeValid1;
	float							m_min1, m_max1;
	bool							m_paramRangeValid2;
	float							m_min2, m_max2;
	bool							m_paramRangeValid3;
	float							m_min3, m_max3;
	bool							m_paramRangeValid4;
	float							m_min4, m_max4;

	ParamVariable<StoredType1>		m_param1;
	ParamVariable<StoredType2>		m_param2;
	ParamVariable<StoredType3>		m_param3;
	ParamVariable<StoredType4>		m_param4;
};


template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
class CGenericMethod4 : public CGenericMethod4_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>
{
public:
	typedef typename CGenericMethod4_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::StoredType1 StoredType1;
	typedef typename CGenericMethod4_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::StoredType2 StoredType2;
	typedef typename CGenericMethod4_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::StoredType3 StoredType3;
	typedef typename CGenericMethod4_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::StoredType4 StoredType4;
	typedef typename CGenericMethod4_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod4_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::ParamBaseType2 ParamBaseType2;
	typedef typename CGenericMethod4_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::ParamBaseType3 ParamBaseType3;
	typedef typename CGenericMethod4_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::ParamBaseType4 ParamBaseType4;

	CGenericMethod4(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4),
		const char* className, const char* propertyName) :
		CGenericMethod4_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>(methodPtr, className, propertyName)
	{}

	CGenericMethod4(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4) const,
		const char* className, const char* propertyName) :
		CGenericMethod4_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod4()
	{
	}

	virtual behaviac::Property* CreateProperty(const char* defaultValue, bool bConst) const
	{
		behaviac::Property* pProperty = behaviac::Property::Creator<R>(defaultValue, 0, bConst);

		return pProperty;
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod4(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);

			R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1, 
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3, 
				(PARAM_CALLEDTYPE(ParamType4))v4);

			if (this->m_return)
			{
				*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
			}

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
		}
	}
#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 4);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);

		R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3, 
			(PARAM_CALLEDTYPE(ParamType4))p4);

		if (this->m_return)
		{
			*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
		}
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};

template<class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
class CGenericMethod4<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4> : public CGenericMethod4_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>
{
public:
	typedef typename CGenericMethod4_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::StoredType1 StoredType1;
	typedef typename CGenericMethod4_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::StoredType2 StoredType2;
	typedef typename CGenericMethod4_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::StoredType3 StoredType3;
	typedef typename CGenericMethod4_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::StoredType4 StoredType4;
	typedef typename CGenericMethod4_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod4_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::ParamBaseType2 ParamBaseType2;
	typedef typename CGenericMethod4_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::ParamBaseType3 ParamBaseType3;
	typedef typename CGenericMethod4_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>::ParamBaseType4 ParamBaseType4;

	CGenericMethod4(void (ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4),
		const char* className, const char* propertyName) :
		CGenericMethod4_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>(methodPtr, className, propertyName)
	{}

	CGenericMethod4(void (ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4) const,
		const char* className, const char* propertyName) :
		CGenericMethod4_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod4()
	{
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod4(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1, 
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3, 
				(PARAM_CALLEDTYPE(ParamType4))v4);

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
		}
	}
#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 4);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);

		(((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3, 
			(PARAM_CALLEDTYPE(ParamType4))p4);
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};

/////////////////////////////////////////////////////////
////////////////     CGenericMethod5_     ///////////////
/////////////////////////////////////////////////////////

template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
class CGenericMethod5_ : public CMethodBase
{
public:
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CGenericMethod5_);

	typedef PARAM_BASETYPE(ParamType1)				ParamBaseType1;
	typedef PARAM_BASETYPE(ParamType2)				ParamBaseType2;
	typedef PARAM_BASETYPE(ParamType3)				ParamBaseType3;
	typedef PARAM_BASETYPE(ParamType4)				ParamBaseType4;
	typedef PARAM_BASETYPE(ParamType5)				ParamBaseType5;

	typedef PARAM_POINTERTYPE(ParamType1)			ParamPointerType1;
	typedef PARAM_POINTERTYPE(ParamType2)			ParamPointerType2;
	typedef PARAM_POINTERTYPE(ParamType3)			ParamPointerType3;
	typedef PARAM_POINTERTYPE(ParamType4)			ParamPointerType4;
	typedef PARAM_POINTERTYPE(ParamType5)			ParamPointerType5;

	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType1>::Result, VALUE_TYPE(ParamType1), ParamBaseType1>::Result StoredType1;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType2>::Result, VALUE_TYPE(ParamType2), ParamBaseType2>::Result StoredType2;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType3>::Result, VALUE_TYPE(ParamType3), ParamBaseType3>::Result StoredType3;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType4>::Result, VALUE_TYPE(ParamType4), ParamBaseType4>::Result StoredType4;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType5>::Result, VALUE_TYPE(ParamType5), ParamBaseType5>::Result StoredType5;

	CGenericMethod5_(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5), 
		const char* className, const char* propertyName) :
		CMethodBase(propertyName, className), m_methodPtr(methodPtr),
		m_paramRangeValid1(false), m_paramRangeValid2(false), m_paramRangeValid3(false), m_paramRangeValid4(false), m_paramRangeValid5(false),
		m_param1(), m_param2(), m_param3(), m_param4(), m_param5()
	{
	}

	typedef R (ObjectType::*MethodType_t)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5);

	CGenericMethod5_(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5) const, 
		const char* className, const char* propertyName) :
		CMethodBase(propertyName, className), m_methodPtr(MethodType_t(methodPtr)),
		m_paramRangeValid1(false), m_paramRangeValid2(false), m_paramRangeValid3(false), m_paramRangeValid4(false), m_paramRangeValid5(false),
		m_param1(), m_param2(), m_param3(), m_param4(), m_param5()
	{
	}

	CGenericMethod5_(const CGenericMethod5_& copy) : CMethodBase(copy)
	{
		this->m_methodPtr = copy.m_methodPtr;

		this->m_paramDisplayName1 = copy.m_paramDisplayName1;
		this->m_paramDisplayName2 = copy.m_paramDisplayName2;
		this->m_paramDisplayName3 = copy.m_paramDisplayName3;
		this->m_paramDisplayName4 = copy.m_paramDisplayName4;
		this->m_paramDisplayName5 = copy.m_paramDisplayName5;

		this->m_param1 = copy.m_param1;
		this->m_param2 = copy.m_param2;
		this->m_param3 = copy.m_param3;
		this->m_param4 = copy.m_param4;
		this->m_param5 = copy.m_param5;
		this->m_paramRangeValid1 = copy.m_paramRangeValid1;
		this->m_paramRangeValid2 = copy.m_paramRangeValid2;
		this->m_paramRangeValid3 = copy.m_paramRangeValid3;
		this->m_paramRangeValid4 = copy.m_paramRangeValid4;
		this->m_paramRangeValid5 = copy.m_paramRangeValid5;
	}

	virtual void LoadFromXML(CTagObject* parent, const ISerializableNode& xmlNode)
	{
		this->m_param1.LoadFromXML(parent, xmlNode, "param1");
		this->m_param2.LoadFromXML(parent, xmlNode, "param2");
		this->m_param3.LoadFromXML(parent, xmlNode, "param3");
		this->m_param4.LoadFromXML(parent, xmlNode, "param4");
		this->m_param5.LoadFromXML(parent, xmlNode, "param5");
	}

	virtual void SaveToXML(const CTagObject* parent, ISerializableNode& xmlNode)
	{
		this->m_param1.SaveToXML(parent, xmlNode, "param1");
		this->m_param2.SaveToXML(parent, xmlNode, "param2");
		this->m_param3.SaveToXML(parent, xmlNode, "param3");
		this->m_param4.SaveToXML(parent, xmlNode, "param4");
		this->m_param5.SaveToXML(parent, xmlNode, "param5");
	}

	virtual void GetUiInfo(CTagTypeDescriptor::TypesMap_t* types, const CTagObject* parent, const XmlNodeRef& xmlNode)
	{
		BEHAVIAC_UNUSED_VAR(parent);

		XmlNodeRef memberNode = xmlNode;
		if (types == NULL)
		{
			memberNode = xmlNode->newChild("Method");
			memberNode->setAttr("Name", this->m_propertyName);
			memberNode->setAttr("DisplayName", this->GetDisplayName());
			memberNode->setAttr("Desc", this->GetDesc());

			if (this->m_flag & CMethodBase::KMETHOD_NAMEDEVENT)
			{
				memberNode->setAttr("Flag", "namedevent");
			}
			if (this->m_classFullName)
			{
				memberNode->setAttr("Class", this->m_classFullName);
			}
			if (m_bStatic)
			{
				memberNode->setAttr("Static", "true");
			}
			if (this->IsActionMethodOnly())
			{
				memberNode->setAttr("IsActionMethodOnly", "true");
			}

			//const char* pReturn = GetClassTypeName((R*)0);
			//memberNode->setAttr("ReturnType", pReturn);
			behaviac::string returnTypeStr = ::GetTypeDescString<R>();
			memberNode->setAttr("ReturnType", returnTypeStr.c_str());
		}

		UserTypeInfoExport<R>::Export(types, true, memberNode);

		XmlNodeRef paramNode = memberNode;
		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName1);
			paramNode->setAttr("Desc", m_paramDesc1);

			behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
			paramNode->setAttr("Type", typeStr1.c_str());
			if (this->m_param1.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param1.GetValue());
			}
			if (m_paramRangeValid1)
			{
				paramNode->setAttr("RangeMin", m_min1);
				paramNode->setAttr("RangeMax", m_max1);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType1, behaviac::Meta::IsEnum<ParamBaseType1>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName2);
			paramNode->setAttr("Desc", m_paramDesc2);

			behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
			paramNode->setAttr("Type", typeStr2.c_str());
			if (this->m_param2.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param2.GetValue());
			}
			if (m_paramRangeValid2)
			{
				paramNode->setAttr("RangeMin", m_min2);
				paramNode->setAttr("RangeMax", m_max2);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType2, behaviac::Meta::IsEnum<ParamBaseType2>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName3);
			paramNode->setAttr("Desc", m_paramDesc3);

			behaviac::string typeStr3 = ::GetTypeDescString<ParamType3>();
			paramNode->setAttr("Type", typeStr3.c_str());
			if (this->m_param3.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param3.GetValue());
			}
			if (m_paramRangeValid3)
			{
				paramNode->setAttr("RangeMin", m_min3);
				paramNode->setAttr("RangeMax", m_max3);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType3, behaviac::Meta::IsEnum<ParamBaseType3>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName4);
			paramNode->setAttr("Desc", m_paramDesc4);

			behaviac::string typeStr4 = ::GetTypeDescString<ParamType4>();
			paramNode->setAttr("Type", typeStr4.c_str());
			if (this->m_param4.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param4.GetValue());
			}
			if (m_paramRangeValid4)
			{
				paramNode->setAttr("RangeMin", m_min4);
				paramNode->setAttr("RangeMax", m_max4);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType4, behaviac::Meta::IsEnum<ParamBaseType4>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName5);
			paramNode->setAttr("Desc", m_paramDesc5);

			behaviac::string typeStr5 = ::GetTypeDescString<ParamType5>();
			paramNode->setAttr("Type", typeStr5.c_str());
			if (this->m_param5.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param5.GetValue());
			}
			if (m_paramRangeValid5)
			{
				paramNode->setAttr("RangeMin", m_min5);
				paramNode->setAttr("RangeMax", m_max5);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType5, behaviac::Meta::IsEnum<ParamBaseType5>::Result>::GetUiInfo(types, paramNode);
	}

	virtual CMethodBase& PARAM_DISPLAYNAME(const wchar_t* paramDisplayName)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
		}
		else if (m_paramDisplayName3.empty())
		{
			m_paramDisplayName3 = paramDisplayName;
		}
		else if (m_paramDisplayName4.empty())
		{
			m_paramDisplayName4 = paramDisplayName;
		}
		else if (m_paramDisplayName5.empty())
		{
			m_paramDisplayName5 = paramDisplayName;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DESC(const wchar_t* paramDesc)
	{
		BEHAVIAC_UNUSED_VAR(paramDesc);

		if (m_paramDesc1.empty())
		{
			m_paramDesc1 = paramDesc;
		}
		else if (m_paramDesc2.empty())
		{
			m_paramDesc2 = paramDesc;
		}
		else if (m_paramDesc3.empty())
		{
			m_paramDesc3 = paramDesc;
		}
		else if (m_paramDesc4.empty())
		{
			m_paramDesc4 = paramDesc;
		}
		else if (m_paramDesc5.empty())
		{
			m_paramDesc5 = paramDesc;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DISPLAY_INFO(const wchar_t* paramDisplayName, const wchar_t* paramDesc = 0, const DefaultParam_t& defaultParam = DefaultParam_t(), float rangeMin = CMETHODBASE_RANGE_MIN_DEFAULT, float rangeMax = CMETHODBASE_RANGE_MAX_DEFAULT)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);
		BEHAVIAC_UNUSED_VAR(paramDesc);
		BEHAVIAC_UNUSED_VAR(defaultParam);
		BEHAVIAC_UNUSED_VAR(rangeMin);
		BEHAVIAC_UNUSED_VAR(rangeMax);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
			m_paramDesc1 = (paramDesc == 0 ?  m_paramDisplayName1 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType1, ParamBaseType1, behaviac::Meta::IsAgent<ParamType1>::Result>::SetValue(this->m_param1, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType1>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid1 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min1 = rangeMin;
				this->m_max1 = rangeMax;
			}
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
			m_paramDesc2 = (paramDesc == 0 ?  m_paramDisplayName2 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType2, ParamBaseType2, behaviac::Meta::IsAgent<ParamType2>::Result>::SetValue(this->m_param2, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType2>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid2 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min2 = rangeMin;
				this->m_max2 = rangeMax;
			}
		}
		else if (m_paramDisplayName3.empty())
		{
			m_paramDisplayName3 = paramDisplayName;
			m_paramDesc3 = (paramDesc == 0 ?  m_paramDisplayName3 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType3, ParamBaseType3, behaviac::Meta::IsAgent<ParamType3>::Result>::SetValue(this->m_param3, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType3>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid3 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min3 = rangeMin;
				this->m_max3 = rangeMax;
			}
		}
		else if (m_paramDisplayName4.empty())
		{
			m_paramDisplayName4 = paramDisplayName;
			m_paramDesc4 = (paramDesc == 0 ?  m_paramDisplayName4 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType4, ParamBaseType4, behaviac::Meta::IsAgent<ParamType4>::Result>::SetValue(this->m_param4, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType4>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid4 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min4 = rangeMin;
				this->m_max4 = rangeMax;
			}
		}
		else if (m_paramDisplayName5.empty())
		{
			m_paramDisplayName5 = paramDisplayName;
			m_paramDesc5 = (paramDesc == 0 ?  m_paramDisplayName5 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType5, ParamBaseType5, behaviac::Meta::IsAgent<ParamType5>::Result>::SetValue(this->m_param5, defaultParam);
			}

			int typeId = GetClassTypeNumberId<ParamBaseType5>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid5 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min5 = rangeMin;
				this->m_max5 = rangeMax;
			}
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual int GetParams()
	{
		return 5;
	}

	virtual behaviac::string GetParamTypeName(uint32_t idx)
	{
		switch (idx)
		{
		case 0:
			{
				behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
				return typeStr1;
			}

		case 1:
			{
				behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
				return typeStr2;
			}

		case 2:
			{
				behaviac::string typeStr3 = ::GetTypeDescString<ParamType3>();
				return typeStr3;
			}

		case 3:
			{
				behaviac::string typeStr4 = ::GetTypeDescString<ParamType4>();
				return typeStr4;
			}

		case 4:
			{
				behaviac::string typeStr5 = ::GetTypeDescString<ParamType5>();
				return typeStr5;
			}

		default:
			return "";
		}
	}

	virtual void vCall(const CTagObject* parent, const void* param1, const void* param2, const void* param3, const void* param4, const void* param5)
	{
		(((ObjectType*)parent)->*this->m_methodPtr)(*(ParamPointerType1)param1, *(ParamPointerType2)param2, *(ParamPointerType3)param3, *(ParamPointerType4)param4, *(ParamPointerType5)param5);
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod5_(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
				const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4,
					(PARAM_CALLEDTYPE(ParamType5))v5);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
			const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1,
				(PARAM_CALLEDTYPE(ParamType2))v2,
				(PARAM_CALLEDTYPE(ParamType3))v3,
				(PARAM_CALLEDTYPE(ParamType4))v4,
				(PARAM_CALLEDTYPE(ParamType5))v5);

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
			this->m_param5.SetVariableRegistry(parHolder, v5);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 5);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);
		PARAM_BASETYPE(ParamType5) p5;
		params[4]->GetValue(p5);

		(((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3, 
			(PARAM_CALLEDTYPE(ParamType4))p4,
			(PARAM_CALLEDTYPE(ParamType5))p5);
	}
#endif//BEHAVIAC_ENABLE_NETWORKD

protected:
	R(ObjectType::*m_methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5);

	behaviac::wstring				m_paramDisplayName1;
	behaviac::wstring				m_paramDesc1;
	behaviac::wstring				m_paramDisplayName2;
	behaviac::wstring				m_paramDesc2;
	behaviac::wstring				m_paramDisplayName3;
	behaviac::wstring				m_paramDesc3;
	behaviac::wstring				m_paramDisplayName4;
	behaviac::wstring				m_paramDesc4;
	behaviac::wstring				m_paramDisplayName5;
	behaviac::wstring				m_paramDesc5;

	bool							m_paramRangeValid1;
	float							m_min1, m_max1;
	bool							m_paramRangeValid2;
	float							m_min2, m_max2;
	bool							m_paramRangeValid3;
	float							m_min3, m_max3;
	bool							m_paramRangeValid4;
	float							m_min4, m_max4;
	bool							m_paramRangeValid5;
	float							m_min5, m_max5;

	ParamVariable<StoredType1>		m_param1;
	ParamVariable<StoredType2>		m_param2;
	ParamVariable<StoredType3>		m_param3;
	ParamVariable<StoredType4>		m_param4;
	ParamVariable<StoredType5>		m_param5;
};


template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
class CGenericMethod5 : public CGenericMethod5_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>
{
public:
	typedef typename CGenericMethod5_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::StoredType1 StoredType1;
	typedef typename CGenericMethod5_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::StoredType2 StoredType2;
	typedef typename CGenericMethod5_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::StoredType3 StoredType3;
	typedef typename CGenericMethod5_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::StoredType4 StoredType4;
	typedef typename CGenericMethod5_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::StoredType5 StoredType5;
	typedef typename CGenericMethod5_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod5_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::ParamBaseType2 ParamBaseType2;
	typedef typename CGenericMethod5_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::ParamBaseType3 ParamBaseType3;
	typedef typename CGenericMethod5_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::ParamBaseType4 ParamBaseType4;
	typedef typename CGenericMethod5_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::ParamBaseType5 ParamBaseType5;

	CGenericMethod5(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5),
		const char* className, const char* propertyName) :
		CGenericMethod5_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>(methodPtr, className, propertyName)
	{}

	CGenericMethod5(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5) const,
		const char* className, const char* propertyName) :
		CGenericMethod5_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod5()
	{
	}

	virtual behaviac::Property* CreateProperty(const char* defaultValue, bool bConst) const
	{
		behaviac::Property* pProperty = behaviac::Property::Creator<R>(defaultValue, 0, bConst);

		return pProperty;
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod5(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
				const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4,
					(PARAM_CALLEDTYPE(ParamType5))v5);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
			const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);

			R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1,
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3,
				(PARAM_CALLEDTYPE(ParamType4))v4,
				(PARAM_CALLEDTYPE(ParamType5))v5);

			if (this->m_return)
			{
				*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
			}

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
			this->m_param5.SetVariableRegistry(parHolder, v5);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 5);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);
		PARAM_BASETYPE(ParamType5) p5;
		params[4]->GetValue(p5);

		R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1,
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3,
			(PARAM_CALLEDTYPE(ParamType4))p4,
			(PARAM_CALLEDTYPE(ParamType5))p5);

		if (this->m_return)
		{
			*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
		}
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};

template<class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
class CGenericMethod5<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> : public CGenericMethod5_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>
{
public:
	typedef typename CGenericMethod5_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::StoredType1 StoredType1;
	typedef typename CGenericMethod5_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::StoredType2 StoredType2;
	typedef typename CGenericMethod5_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::StoredType3 StoredType3;
	typedef typename CGenericMethod5_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::StoredType4 StoredType4;
	typedef typename CGenericMethod5_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::StoredType5 StoredType5;
	typedef typename CGenericMethod5_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod5_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::ParamBaseType2 ParamBaseType2;
	typedef typename CGenericMethod5_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::ParamBaseType3 ParamBaseType3;
	typedef typename CGenericMethod5_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::ParamBaseType4 ParamBaseType4;
	typedef typename CGenericMethod5_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>::ParamBaseType5 ParamBaseType5;

	CGenericMethod5(void (ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5),
		const char* className, const char* propertyName) :
		CGenericMethod5_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>(methodPtr, className, propertyName)
	{}

	CGenericMethod5(void (ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5) const,
		const char* className, const char* propertyName) :
		CGenericMethod5_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod5()
	{
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod5(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
				const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4, ParamType5>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4,
					(PARAM_CALLEDTYPE(ParamType5))v5);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
			const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1, 
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3, 
				(PARAM_CALLEDTYPE(ParamType4))v4,
				(PARAM_CALLEDTYPE(ParamType5))v5);

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
			this->m_param5.SetVariableRegistry(parHolder, v5);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 5);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);
		PARAM_BASETYPE(ParamType5) p5;
		params[4]->GetValue(p5);

		(((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3, 
			(PARAM_CALLEDTYPE(ParamType4))p4,
			(PARAM_CALLEDTYPE(ParamType5))p5);
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};

/////////////////////////////////////////////////////////
////////////////     CGenericMethod6_     ///////////////
/////////////////////////////////////////////////////////

template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
class CGenericMethod6_ : public CMethodBase
{
public:
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CGenericMethod6_);

	typedef PARAM_BASETYPE(ParamType1)				ParamBaseType1;
	typedef PARAM_BASETYPE(ParamType2)				ParamBaseType2;
	typedef PARAM_BASETYPE(ParamType3)				ParamBaseType3;
	typedef PARAM_BASETYPE(ParamType4)				ParamBaseType4;
	typedef PARAM_BASETYPE(ParamType5)				ParamBaseType5;
	typedef PARAM_BASETYPE(ParamType6)				ParamBaseType6;

	typedef PARAM_POINTERTYPE(ParamType1)			ParamPointerType1;
	typedef PARAM_POINTERTYPE(ParamType2)			ParamPointerType2;
	typedef PARAM_POINTERTYPE(ParamType3)			ParamPointerType3;
	typedef PARAM_POINTERTYPE(ParamType4)			ParamPointerType4;
	typedef PARAM_POINTERTYPE(ParamType5)			ParamPointerType5;
	typedef PARAM_POINTERTYPE(ParamType6)			ParamPointerType6;

	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType1>::Result, VALUE_TYPE(ParamType1), ParamBaseType1>::Result StoredType1;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType2>::Result, VALUE_TYPE(ParamType2), ParamBaseType2>::Result StoredType2;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType3>::Result, VALUE_TYPE(ParamType3), ParamBaseType3>::Result StoredType3;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType4>::Result, VALUE_TYPE(ParamType4), ParamBaseType4>::Result StoredType4;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType5>::Result, VALUE_TYPE(ParamType5), ParamBaseType5>::Result StoredType5;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType6>::Result, VALUE_TYPE(ParamType6), ParamBaseType6>::Result StoredType6;

	CGenericMethod6_(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6), 
		const char* className, const char* propertyName) :
		CMethodBase(propertyName, className), m_methodPtr(methodPtr),
		m_paramRangeValid1(false), m_paramRangeValid2(false), m_paramRangeValid3(false), m_paramRangeValid4(false), m_paramRangeValid5(false), m_paramRangeValid6(false),
		m_param1(), m_param2(), m_param3(), m_param4(), m_param5(), m_param6()
	{
	}

	typedef R (ObjectType::*MethodType_t)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6);

	CGenericMethod6_(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6) const, 
		const char* className, const char* propertyName) :
		CMethodBase(propertyName, className), m_methodPtr(MethodType_t(methodPtr)),
		m_paramRangeValid1(false), m_paramRangeValid2(false), m_paramRangeValid3(false), m_paramRangeValid4(false), m_paramRangeValid5(false), m_paramRangeValid6(false),
		m_param1(), m_param2(), m_param3(), m_param4(), m_param5(), m_param6()
	{
	}

	CGenericMethod6_(const CGenericMethod6_& copy) : CMethodBase(copy)
	{
		this->m_methodPtr = copy.m_methodPtr;

		this->m_paramDisplayName1 = copy.m_paramDisplayName1;
		this->m_paramDisplayName2 = copy.m_paramDisplayName2;
		this->m_paramDisplayName3 = copy.m_paramDisplayName3;
		this->m_paramDisplayName4 = copy.m_paramDisplayName4;
		this->m_paramDisplayName5 = copy.m_paramDisplayName5;
		this->m_paramDisplayName6 = copy.m_paramDisplayName6;

		this->m_param1 = copy.m_param1;
		this->m_param2 = copy.m_param2;
		this->m_param3 = copy.m_param3;
		this->m_param4 = copy.m_param4;
		this->m_param5 = copy.m_param5;
		this->m_param6 = copy.m_param6;
		this->m_paramRangeValid1 = copy.m_paramRangeValid1;
		this->m_paramRangeValid2 = copy.m_paramRangeValid2;
		this->m_paramRangeValid3 = copy.m_paramRangeValid3;
		this->m_paramRangeValid4 = copy.m_paramRangeValid4;
		this->m_paramRangeValid5 = copy.m_paramRangeValid5;
		this->m_paramRangeValid6 = copy.m_paramRangeValid6;
	}

	virtual void LoadFromXML(CTagObject* parent, const ISerializableNode& xmlNode)
	{
		this->m_param1.LoadFromXML(parent, xmlNode, "param1");
		this->m_param2.LoadFromXML(parent, xmlNode, "param2");
		this->m_param3.LoadFromXML(parent, xmlNode, "param3");
		this->m_param4.LoadFromXML(parent, xmlNode, "param4");
		this->m_param5.LoadFromXML(parent, xmlNode, "param5");
		this->m_param6.LoadFromXML(parent, xmlNode, "param6");
	}

	virtual void SaveToXML(const CTagObject* parent, ISerializableNode& xmlNode)
	{
		this->m_param1.SaveToXML(parent, xmlNode, "param1");
		this->m_param2.SaveToXML(parent, xmlNode, "param2");
		this->m_param3.SaveToXML(parent, xmlNode, "param3");
		this->m_param4.SaveToXML(parent, xmlNode, "param4");
		this->m_param5.SaveToXML(parent, xmlNode, "param5");
		this->m_param6.SaveToXML(parent, xmlNode, "param6");
	}

	virtual void GetUiInfo(CTagTypeDescriptor::TypesMap_t* types, const CTagObject* parent, const XmlNodeRef& xmlNode)
	{
		BEHAVIAC_UNUSED_VAR(parent);

		XmlNodeRef memberNode = xmlNode;
		if (types == NULL)
		{
			memberNode = xmlNode->newChild("Method");
			memberNode->setAttr("Name", this->m_propertyName);
			memberNode->setAttr("DisplayName", this->GetDisplayName());
			memberNode->setAttr("Desc", this->GetDesc());

			if (this->m_flag & CMethodBase::KMETHOD_NAMEDEVENT)
			{
				memberNode->setAttr("Flag", "namedevent");
			}
			if (this->m_classFullName)
			{
				memberNode->setAttr("Class", this->m_classFullName);
			}
			if (m_bStatic)
			{
				memberNode->setAttr("Static", "true");
			}
			if (this->IsActionMethodOnly())
			{
				memberNode->setAttr("IsActionMethodOnly", "true");
			}

			//const char* pReturn = GetClassTypeName((R*)0);
			//memberNode->setAttr("ReturnType", pReturn);
			behaviac::string returnTypeStr = ::GetTypeDescString<R>();
			memberNode->setAttr("ReturnType", returnTypeStr.c_str());
		}

		UserTypeInfoExport<R>::Export(types, true, memberNode);

		XmlNodeRef paramNode = memberNode;
		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName1);
			paramNode->setAttr("Desc", m_paramDesc1);

			behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
			paramNode->setAttr("Type", typeStr1.c_str());
			if (this->m_param1.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param1.GetValue());
			}
			if (m_paramRangeValid1)
			{
				paramNode->setAttr("RangeMin", m_min1);
				paramNode->setAttr("RangeMax", m_max1);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType1, behaviac::Meta::IsEnum<ParamBaseType1>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName2);
			paramNode->setAttr("Desc", m_paramDesc2);

			behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
			paramNode->setAttr("Type", typeStr2.c_str());
			if (this->m_param2.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param2.GetValue());
			}
			if (m_paramRangeValid2)
			{
				paramNode->setAttr("RangeMin", m_min2);
				paramNode->setAttr("RangeMax", m_max2);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType2, behaviac::Meta::IsEnum<ParamBaseType2>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName3);
			paramNode->setAttr("Desc", m_paramDesc3);

			behaviac::string typeStr3 = ::GetTypeDescString<ParamType3>();
			paramNode->setAttr("Type", typeStr3.c_str());
			if (this->m_param3.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param3.GetValue());
			}
			if (m_paramRangeValid3)
			{
				paramNode->setAttr("RangeMin", m_min3);
				paramNode->setAttr("RangeMax", m_max3);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType3, behaviac::Meta::IsEnum<ParamBaseType3>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName4);
			paramNode->setAttr("Desc", m_paramDesc4);

			behaviac::string typeStr4 = ::GetTypeDescString<ParamType4>();
			paramNode->setAttr("Type", typeStr4.c_str());
			if (this->m_param4.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param4.GetValue());
			}
			if (m_paramRangeValid4)
			{
				paramNode->setAttr("RangeMin", m_min4);
				paramNode->setAttr("RangeMax", m_max4);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType4, behaviac::Meta::IsEnum<ParamBaseType4>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName5);
			paramNode->setAttr("Desc", m_paramDesc5);

			behaviac::string typeStr5 = ::GetTypeDescString<ParamType5>();
			paramNode->setAttr("Type", typeStr5.c_str());
			if (this->m_param5.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param5.GetValue());
			}
			if (m_paramRangeValid5)
			{
				paramNode->setAttr("RangeMin", m_min5);
				paramNode->setAttr("RangeMax", m_max5);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType5, behaviac::Meta::IsEnum<ParamBaseType5>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName6);
			paramNode->setAttr("Desc", m_paramDesc6);

			behaviac::string typeStr6 = ::GetTypeDescString<ParamType6>();
			paramNode->setAttr("Type", typeStr6.c_str());
			if (this->m_param6.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param6.GetValue());
			}
			if (m_paramRangeValid6)
			{
				paramNode->setAttr("RangeMin", m_min6);
				paramNode->setAttr("RangeMax", m_max6);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType6, behaviac::Meta::IsEnum<ParamBaseType6>::Result>::GetUiInfo(types, paramNode);
	}

	virtual CMethodBase& PARAM_DISPLAYNAME(const wchar_t* paramDisplayName)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
		}
		else if (m_paramDisplayName3.empty())
		{
			m_paramDisplayName3 = paramDisplayName;
		}
		else if (m_paramDisplayName4.empty())
		{
			m_paramDisplayName4 = paramDisplayName;
		}
		else if (m_paramDisplayName5.empty())
		{
			m_paramDisplayName5 = paramDisplayName;
		}
		else if (m_paramDisplayName6.empty())
		{
			m_paramDisplayName6 = paramDisplayName;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DESC(const wchar_t* paramDesc)
	{
		BEHAVIAC_UNUSED_VAR(paramDesc);


		if (m_paramDesc1.empty())
		{
			m_paramDesc1 = paramDesc;
		}
		else if (m_paramDesc2.empty())
		{
			m_paramDesc2 = paramDesc;
		}
		else if (m_paramDesc3.empty())
		{
			m_paramDesc3 = paramDesc;
		}
		else if (m_paramDesc4.empty())
		{
			m_paramDesc4 = paramDesc;
		}
		else if (m_paramDesc5.empty())
		{
			m_paramDesc5 = paramDesc;
		}
		else if (m_paramDesc6.empty())
		{
			m_paramDesc6 = paramDesc;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DISPLAY_INFO(const wchar_t* paramDisplayName, const wchar_t* paramDesc = 0, const DefaultParam_t& defaultParam = DefaultParam_t(), float rangeMin = CMETHODBASE_RANGE_MIN_DEFAULT, float rangeMax = CMETHODBASE_RANGE_MAX_DEFAULT)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);
		BEHAVIAC_UNUSED_VAR(paramDesc);
		BEHAVIAC_UNUSED_VAR(defaultParam);
		BEHAVIAC_UNUSED_VAR(rangeMin);
		BEHAVIAC_UNUSED_VAR(rangeMax);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
			m_paramDesc1 = (paramDesc == 0 ?  m_paramDisplayName1 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType1, ParamBaseType1, behaviac::Meta::IsAgent<ParamType1>::Result>::SetValue(this->m_param1, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType1>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid1 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min1 = rangeMin;
				this->m_max1 = rangeMax;
			}
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
			m_paramDesc2 = (paramDesc == 0 ?  m_paramDisplayName2 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType2, ParamBaseType2, behaviac::Meta::IsAgent<ParamType2>::Result>::SetValue(this->m_param2, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType2>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid2 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min2 = rangeMin;
				this->m_max2 = rangeMax;
			}
		}
		else if (m_paramDisplayName3.empty())
		{
			m_paramDisplayName3 = paramDisplayName;
			m_paramDesc3 = (paramDesc == 0 ?  m_paramDisplayName3 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType3, ParamBaseType3, behaviac::Meta::IsAgent<ParamType3>::Result>::SetValue(this->m_param3, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType3>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid3 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min3 = rangeMin;
				this->m_max3 = rangeMax;
			}
		}
		else if (m_paramDisplayName4.empty())
		{
			m_paramDisplayName4 = paramDisplayName;
			m_paramDesc4 = (paramDesc == 0 ?  m_paramDisplayName4 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType4, ParamBaseType4, behaviac::Meta::IsAgent<ParamType4>::Result>::SetValue(this->m_param4, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType4>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid4 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min4 = rangeMin;
				this->m_max4 = rangeMax;
			}
		}
		else if (m_paramDisplayName5.empty())
		{
			m_paramDisplayName5 = paramDisplayName;
			m_paramDesc5 = (paramDesc == 0 ?  m_paramDisplayName5 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType5, ParamBaseType5, behaviac::Meta::IsAgent<ParamType5>::Result>::SetValue(this->m_param5, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType5>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid5 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min5 = rangeMin;
				this->m_max5 = rangeMax;
			}
		}
		else if (m_paramDisplayName6.empty())
		{
			m_paramDisplayName6 = paramDisplayName;
			m_paramDesc6 = (paramDesc == 0 ?  m_paramDisplayName6 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType6, ParamBaseType6, behaviac::Meta::IsAgent<ParamType6>::Result>::SetValue(this->m_param6, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType6>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid6 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min6 = rangeMin;
				this->m_max6 = rangeMax;
			}
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual int GetParams()
	{
		return 6;
	}

	virtual behaviac::string GetParamTypeName(uint32_t idx)
	{
		switch (idx)
		{
		case 0:
			{
				behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
				return typeStr1;
			}

		case 1:
			{
				behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
				return typeStr2;
			}

		case 2:
			{
				behaviac::string typeStr3 = ::GetTypeDescString<ParamType3>();
				return typeStr3;
			}

		case 3:
			{
				behaviac::string typeStr4 = ::GetTypeDescString<ParamType4>();
				return typeStr4;
			}

		case 4:
			{
				behaviac::string typeStr5 = ::GetTypeDescString<ParamType5>();
				return typeStr5;
			}

		case 5:
			{
				behaviac::string typeStr6 = ::GetTypeDescString<ParamType6>();
				return typeStr6;
			}

		default:
			return "";
		}
	}

	virtual void vCall(const CTagObject* parent, const void* param1, const void* param2, const void* param3, const void* param4, const void* param5, const void* param6)
	{
		(((ObjectType*)parent)->*this->m_methodPtr)(*(ParamPointerType1)param1, *(ParamPointerType2)param2, *(ParamPointerType3)param3, *(ParamPointerType4)param4, *(ParamPointerType5)param5, *(ParamPointerType6)param6);
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod6_(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
				const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
				const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4,
					(PARAM_CALLEDTYPE(ParamType5))v5,
					(PARAM_CALLEDTYPE(ParamType6))v6);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
			const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
			const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1,
				(PARAM_CALLEDTYPE(ParamType2))v2,
				(PARAM_CALLEDTYPE(ParamType3))v3,
				(PARAM_CALLEDTYPE(ParamType4))v4,
				(PARAM_CALLEDTYPE(ParamType5))v5,
				(PARAM_CALLEDTYPE(ParamType6))v6);

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
			this->m_param5.SetVariableRegistry(parHolder, v5);
			this->m_param6.SetVariableRegistry(parHolder, v6);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 6);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);
		PARAM_BASETYPE(ParamType5) p5;
		params[4]->GetValue(p5);
		PARAM_BASETYPE(ParamType6) p6;
		params[5]->GetValue(p6);

		(((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3, 
			(PARAM_CALLEDTYPE(ParamType4))p4,
			(PARAM_CALLEDTYPE(ParamType5))p5,
			(PARAM_CALLEDTYPE(ParamType6))p6);
	}
#endif//BEHAVIAC_ENABLE_NETWORKD

protected:
	R(ObjectType::*m_methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6);

	behaviac::wstring				m_paramDisplayName1;
	behaviac::wstring				m_paramDesc1;
	behaviac::wstring				m_paramDisplayName2;
	behaviac::wstring				m_paramDesc2;
	behaviac::wstring				m_paramDisplayName3;
	behaviac::wstring				m_paramDesc3;
	behaviac::wstring				m_paramDisplayName4;
	behaviac::wstring				m_paramDesc4;
	behaviac::wstring				m_paramDisplayName5;
	behaviac::wstring				m_paramDesc5;
	behaviac::wstring				m_paramDisplayName6;
	behaviac::wstring				m_paramDesc6;

	bool							m_paramRangeValid1;
	float							m_min1, m_max1;
	bool							m_paramRangeValid2;
	float							m_min2, m_max2;
	bool							m_paramRangeValid3;
	float							m_min3, m_max3;
	bool							m_paramRangeValid4;
	float							m_min4, m_max4;
	bool							m_paramRangeValid5;
	float							m_min5, m_max5;
	bool							m_paramRangeValid6;
	float							m_min6, m_max6;

	ParamVariable<StoredType1>		m_param1;
	ParamVariable<StoredType2>		m_param2;
	ParamVariable<StoredType3>		m_param3;
	ParamVariable<StoredType4>		m_param4;
	ParamVariable<StoredType5>		m_param5;
	ParamVariable<StoredType6>		m_param6;
};


template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
class CGenericMethod6 : public CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>
{
public:
	typedef typename CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::StoredType1 StoredType1;
	typedef typename CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::StoredType2 StoredType2;
	typedef typename CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::StoredType3 StoredType3;
	typedef typename CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::StoredType4 StoredType4;
	typedef typename CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::StoredType5 StoredType5;
	typedef typename CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::StoredType6 StoredType6;
	typedef typename CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::ParamBaseType2 ParamBaseType2;
	typedef typename CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::ParamBaseType3 ParamBaseType3;
	typedef typename CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::ParamBaseType4 ParamBaseType4;
	typedef typename CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::ParamBaseType5 ParamBaseType5;
	typedef typename CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::ParamBaseType6 ParamBaseType6;

	CGenericMethod6(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6),
		const char* className, const char* propertyName) :
		CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>(methodPtr, className, propertyName)
	{}

	CGenericMethod6(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6) const,
		const char* className, const char* propertyName) :
		CGenericMethod6_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod6()
	{
	}

	virtual behaviac::Property* CreateProperty(const char* defaultValue, bool bConst) const
	{
		behaviac::Property* pProperty = behaviac::Property::Creator<R>(defaultValue, 0, bConst);

		return pProperty;
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod6(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
				const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
				const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4,
					(PARAM_CALLEDTYPE(ParamType5))v5,
					(PARAM_CALLEDTYPE(ParamType6))v6);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
			const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
			const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);

			R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1,
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3,
				(PARAM_CALLEDTYPE(ParamType4))v4,
				(PARAM_CALLEDTYPE(ParamType5))v5,
				(PARAM_CALLEDTYPE(ParamType6))v6);

			if (this->m_return)
			{
				*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
			}

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
			this->m_param5.SetVariableRegistry(parHolder, v5);
			this->m_param6.SetVariableRegistry(parHolder, v6);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 6);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);
		PARAM_BASETYPE(ParamType5) p5;
		params[4]->GetValue(p5);
		PARAM_BASETYPE(ParamType6) p6;
		params[5]->GetValue(p6);

		R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1,
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3,
			(PARAM_CALLEDTYPE(ParamType4))p4,
			(PARAM_CALLEDTYPE(ParamType5))p5,
			(PARAM_CALLEDTYPE(ParamType6))p6);

		if (this->m_return)
		{
			*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
		}
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};

template<class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
class CGenericMethod6<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> : public CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>
{
public:
	typedef typename CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::StoredType1 StoredType1;
	typedef typename CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::StoredType2 StoredType2;
	typedef typename CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::StoredType3 StoredType3;
	typedef typename CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::StoredType4 StoredType4;
	typedef typename CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::StoredType5 StoredType5;
	typedef typename CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::StoredType6 StoredType6;
	typedef typename CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::ParamBaseType2 ParamBaseType2;
	typedef typename CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::ParamBaseType3 ParamBaseType3;
	typedef typename CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::ParamBaseType4 ParamBaseType4;
	typedef typename CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::ParamBaseType5 ParamBaseType5;
	typedef typename CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>::ParamBaseType6 ParamBaseType6;

	CGenericMethod6(void (ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6),
		const char* className, const char* propertyName) :
		CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>(methodPtr, className, propertyName)
	{}

	CGenericMethod6(void (ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6) const,
		const char* className, const char* propertyName) :
		CGenericMethod6_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod6()
	{
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod6(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
				const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
				const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4,
					(PARAM_CALLEDTYPE(ParamType5))v5,
					(PARAM_CALLEDTYPE(ParamType6))v6);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
			const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
			const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1, 
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3, 
				(PARAM_CALLEDTYPE(ParamType4))v4,
				(PARAM_CALLEDTYPE(ParamType5))v5,
				(PARAM_CALLEDTYPE(ParamType6))v6);

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
			this->m_param5.SetVariableRegistry(parHolder, v5);
			this->m_param6.SetVariableRegistry(parHolder, v6);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 6);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);
		PARAM_BASETYPE(ParamType5) p5;
		params[4]->GetValue(p5);
		PARAM_BASETYPE(ParamType6) p6;
		params[5]->GetValue(p6);

		(((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3, 
			(PARAM_CALLEDTYPE(ParamType4))p4,
			(PARAM_CALLEDTYPE(ParamType5))p5,
			(PARAM_CALLEDTYPE(ParamType6))p6);
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};

/////////////////////////////////////////////////////////
////////////////     CGenericMethod7_     ///////////////
/////////////////////////////////////////////////////////

template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
class CGenericMethod7_ : public CMethodBase
{
public:
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CGenericMethod7_);

	typedef PARAM_BASETYPE(ParamType1)				ParamBaseType1;
	typedef PARAM_BASETYPE(ParamType2)				ParamBaseType2;
	typedef PARAM_BASETYPE(ParamType3)				ParamBaseType3;
	typedef PARAM_BASETYPE(ParamType4)				ParamBaseType4;
	typedef PARAM_BASETYPE(ParamType5)				ParamBaseType5;
	typedef PARAM_BASETYPE(ParamType6)				ParamBaseType6;
	typedef PARAM_BASETYPE(ParamType7)				ParamBaseType7;

	typedef PARAM_POINTERTYPE(ParamType1)			ParamPointerType1;
	typedef PARAM_POINTERTYPE(ParamType2)			ParamPointerType2;
	typedef PARAM_POINTERTYPE(ParamType3)			ParamPointerType3;
	typedef PARAM_POINTERTYPE(ParamType4)			ParamPointerType4;
	typedef PARAM_POINTERTYPE(ParamType5)			ParamPointerType5;
	typedef PARAM_POINTERTYPE(ParamType6)			ParamPointerType6;
	typedef PARAM_POINTERTYPE(ParamType7)			ParamPointerType7;

	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType1>::Result, VALUE_TYPE(ParamType1), ParamBaseType1>::Result StoredType1;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType2>::Result, VALUE_TYPE(ParamType2), ParamBaseType2>::Result StoredType2;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType3>::Result, VALUE_TYPE(ParamType3), ParamBaseType3>::Result StoredType3;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType4>::Result, VALUE_TYPE(ParamType4), ParamBaseType4>::Result StoredType4;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType5>::Result, VALUE_TYPE(ParamType5), ParamBaseType5>::Result StoredType5;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType6>::Result, VALUE_TYPE(ParamType6), ParamBaseType6>::Result StoredType6;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType7>::Result, VALUE_TYPE(ParamType7), ParamBaseType7>::Result StoredType7;

	CGenericMethod7_(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7),
		const char* className, const char* propertyName) :
		CMethodBase(propertyName, className), m_methodPtr(methodPtr),
		m_paramRangeValid1(false), m_paramRangeValid2(false), m_paramRangeValid3(false), m_paramRangeValid4(false), m_paramRangeValid5(false), m_paramRangeValid6(false), m_paramRangeValid7(false),
		m_param1(), m_param2(), m_param3(), m_param4(), m_param5(), m_param6(), m_param7()
	{
	}

	typedef R (ObjectType::*MethodType_t)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7);

	CGenericMethod7_(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7) const, 
		const char* className, const char* propertyName) :
		CMethodBase(propertyName, className), m_methodPtr(MethodType_t(methodPtr)),
		m_paramRangeValid1(false), m_paramRangeValid2(false), m_paramRangeValid3(false), m_paramRangeValid4(false), m_paramRangeValid5(false), m_paramRangeValid6(false), m_paramRangeValid7(false),
		m_param1(), m_param2(), m_param3(), m_param4(), m_param5(), m_param6(), m_param7()
	{
	}

	CGenericMethod7_(const CGenericMethod7_& copy) : CMethodBase(copy)
	{
		this->m_methodPtr = copy.m_methodPtr;

		this->m_paramDisplayName1 = copy.m_paramDisplayName1;
		this->m_paramDisplayName2 = copy.m_paramDisplayName2;
		this->m_paramDisplayName3 = copy.m_paramDisplayName3;
		this->m_paramDisplayName4 = copy.m_paramDisplayName4;
		this->m_paramDisplayName5 = copy.m_paramDisplayName5;
		this->m_paramDisplayName6 = copy.m_paramDisplayName6;
		this->m_paramDisplayName7 = copy.m_paramDisplayName7;

		this->m_param1 = copy.m_param1;
		this->m_param2 = copy.m_param2;
		this->m_param3 = copy.m_param3;
		this->m_param4 = copy.m_param4;
		this->m_param5 = copy.m_param5;
		this->m_param6 = copy.m_param6;
		this->m_param7 = copy.m_param7;
		this->m_paramRangeValid1 = copy.m_paramRangeValid1;
		this->m_paramRangeValid2 = copy.m_paramRangeValid2;
		this->m_paramRangeValid3 = copy.m_paramRangeValid3;
		this->m_paramRangeValid4 = copy.m_paramRangeValid4;
		this->m_paramRangeValid5 = copy.m_paramRangeValid5;
		this->m_paramRangeValid6 = copy.m_paramRangeValid6;
		this->m_paramRangeValid7 = copy.m_paramRangeValid7;
	}

	virtual void LoadFromXML(CTagObject* parent, const ISerializableNode& xmlNode)
	{
		this->m_param1.LoadFromXML(parent, xmlNode, "param1");
		this->m_param2.LoadFromXML(parent, xmlNode, "param2");
		this->m_param3.LoadFromXML(parent, xmlNode, "param3");
		this->m_param4.LoadFromXML(parent, xmlNode, "param4");
		this->m_param5.LoadFromXML(parent, xmlNode, "param5");
		this->m_param6.LoadFromXML(parent, xmlNode, "param6");
		this->m_param7.LoadFromXML(parent, xmlNode, "param7");
	}

	virtual void SaveToXML(const CTagObject* parent, ISerializableNode& xmlNode)
	{
		this->m_param1.SaveToXML(parent, xmlNode, "param1");
		this->m_param2.SaveToXML(parent, xmlNode, "param2");
		this->m_param3.SaveToXML(parent, xmlNode, "param3");
		this->m_param4.SaveToXML(parent, xmlNode, "param4");
		this->m_param5.SaveToXML(parent, xmlNode, "param5");
		this->m_param6.SaveToXML(parent, xmlNode, "param6");
		this->m_param7.SaveToXML(parent, xmlNode, "param7");
	}

	virtual void GetUiInfo(CTagTypeDescriptor::TypesMap_t* types, const CTagObject* parent, const XmlNodeRef& xmlNode)
	{
		BEHAVIAC_UNUSED_VAR(parent);

		XmlNodeRef memberNode = xmlNode;
		if (types == NULL)
		{
			memberNode = xmlNode->newChild("Method");
			memberNode->setAttr("Name", this->m_propertyName);
			memberNode->setAttr("DisplayName", this->GetDisplayName());
			memberNode->setAttr("Desc", this->GetDesc());

			if (this->m_flag & CMethodBase::KMETHOD_NAMEDEVENT)
			{
				memberNode->setAttr("Flag", "namedevent");
			}
			if (this->m_classFullName)
			{
				memberNode->setAttr("Class", this->m_classFullName);
			}
			if (m_bStatic)
			{
				memberNode->setAttr("Static", "true");
			}
			if (this->IsActionMethodOnly())
			{
				memberNode->setAttr("IsActionMethodOnly", "true");
			}

			//const char* pReturn = GetClassTypeName((R*)0);
			//memberNode->setAttr("ReturnType", pReturn);
			behaviac::string returnTypeStr = ::GetTypeDescString<R>();
			memberNode->setAttr("ReturnType", returnTypeStr.c_str());
		}

		UserTypeInfoExport<R>::Export(types, true, memberNode);

		XmlNodeRef paramNode = memberNode;
		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName1);
			paramNode->setAttr("Desc", m_paramDesc1);

			behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
			paramNode->setAttr("Type", typeStr1.c_str());
			if (this->m_param1.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param1.GetValue());
			}
			if (m_paramRangeValid1)
			{
				paramNode->setAttr("RangeMin", m_min1);
				paramNode->setAttr("RangeMax", m_max1);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType1, behaviac::Meta::IsEnum<ParamBaseType1>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName2);
			paramNode->setAttr("Desc", m_paramDesc2);

			behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
			paramNode->setAttr("Type", typeStr2.c_str());
			if (this->m_param2.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param2.GetValue());
			}
			if (m_paramRangeValid2)
			{
				paramNode->setAttr("RangeMin", m_min2);
				paramNode->setAttr("RangeMax", m_max2);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType2, behaviac::Meta::IsEnum<ParamBaseType2>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName3);
			paramNode->setAttr("Desc", m_paramDesc3);

			behaviac::string typeStr3 = ::GetTypeDescString<ParamType3>();
			paramNode->setAttr("Type", typeStr3.c_str());
			if (this->m_param3.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param3.GetValue());
			}
			if (m_paramRangeValid3)
			{
				paramNode->setAttr("RangeMin", m_min3);
				paramNode->setAttr("RangeMax", m_max3);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType3, behaviac::Meta::IsEnum<ParamBaseType3>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName4);
			paramNode->setAttr("Desc", m_paramDesc4);

			behaviac::string typeStr4 = ::GetTypeDescString<ParamType4>();
			paramNode->setAttr("Type", typeStr4.c_str());
			if (this->m_param4.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param4.GetValue());
			}
			if (m_paramRangeValid4)
			{
				paramNode->setAttr("RangeMin", m_min4);
				paramNode->setAttr("RangeMax", m_max4);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType4, behaviac::Meta::IsEnum<ParamBaseType4>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName5);
			paramNode->setAttr("Desc", m_paramDesc5);

			behaviac::string typeStr5 = ::GetTypeDescString<ParamType5>();
			paramNode->setAttr("Type", typeStr5.c_str());
			if (this->m_param5.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param5.GetValue());
			}
			if (m_paramRangeValid5)
			{
				paramNode->setAttr("RangeMin", m_min5);
				paramNode->setAttr("RangeMax", m_max5);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType5, behaviac::Meta::IsEnum<ParamBaseType5>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName6);
			paramNode->setAttr("Desc", m_paramDesc6);

			behaviac::string typeStr6 = ::GetTypeDescString<ParamType6>();
			paramNode->setAttr("Type", typeStr6.c_str());
			if (this->m_param6.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param6.GetValue());
			}
			if (m_paramRangeValid6)
			{
				paramNode->setAttr("RangeMin", m_min6);
				paramNode->setAttr("RangeMax", m_max6);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType6, behaviac::Meta::IsEnum<ParamBaseType6>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName7);
			paramNode->setAttr("Desc", m_paramDesc7);

			behaviac::string typeStr7 = ::GetTypeDescString<ParamType7>();
			paramNode->setAttr("Type", typeStr7.c_str());
			if (this->m_param7.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param7.GetValue());
			}
			if (m_paramRangeValid7)
			{
				paramNode->setAttr("RangeMin", m_min7);
				paramNode->setAttr("RangeMax", m_max7);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType7, behaviac::Meta::IsEnum<ParamBaseType7>::Result>::GetUiInfo(types, paramNode);
	}

	virtual CMethodBase& PARAM_DISPLAYNAME(const wchar_t* paramDisplayName)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
		}
		else if (m_paramDisplayName3.empty())
		{
			m_paramDisplayName3 = paramDisplayName;
		}
		else if (m_paramDisplayName4.empty())
		{
			m_paramDisplayName4 = paramDisplayName;
		}
		else if (m_paramDisplayName5.empty())
		{
			m_paramDisplayName5 = paramDisplayName;
		}
		else if (m_paramDisplayName6.empty())
		{
			m_paramDisplayName6 = paramDisplayName;
		}
		else if (m_paramDisplayName7.empty())
		{
			m_paramDisplayName7 = paramDisplayName;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DESC(const wchar_t* paramDesc)
	{
		BEHAVIAC_UNUSED_VAR(paramDesc);


		if (m_paramDesc1.empty())
		{
			m_paramDesc1 = paramDesc;
		}
		else if (m_paramDesc2.empty())
		{
			m_paramDesc2 = paramDesc;
		}
		else if (m_paramDesc3.empty())
		{
			m_paramDesc3 = paramDesc;
		}
		else if (m_paramDesc4.empty())
		{
			m_paramDesc4 = paramDesc;
		}
		else if (m_paramDesc5.empty())
		{
			m_paramDesc5 = paramDesc;
		}
		else if (m_paramDesc6.empty())
		{
			m_paramDesc6 = paramDesc;
		}
		else if (m_paramDesc7.empty())
		{
			m_paramDesc7 = paramDesc;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DISPLAY_INFO(const wchar_t* paramDisplayName, const wchar_t* paramDesc = 0, const DefaultParam_t& defaultParam = DefaultParam_t(), float rangeMin = CMETHODBASE_RANGE_MIN_DEFAULT, float rangeMax = CMETHODBASE_RANGE_MAX_DEFAULT)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);
		BEHAVIAC_UNUSED_VAR(paramDesc);
		BEHAVIAC_UNUSED_VAR(defaultParam);
		BEHAVIAC_UNUSED_VAR(rangeMin);
		BEHAVIAC_UNUSED_VAR(rangeMax);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
			m_paramDesc1 = (paramDesc == 0 ?  m_paramDisplayName1 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType1, ParamBaseType1, behaviac::Meta::IsAgent<ParamType1>::Result>::SetValue(this->m_param1, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType1>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid1 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min1 = rangeMin;
				this->m_max1 = rangeMax;
			}
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
			m_paramDesc2 = (paramDesc == 0 ?  m_paramDisplayName2 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType2, ParamBaseType2, behaviac::Meta::IsAgent<ParamType2>::Result>::SetValue(this->m_param2, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType2>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid2 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min2 = rangeMin;
				this->m_max2 = rangeMax;
			}
		}
		else if (m_paramDisplayName3.empty())
		{
			m_paramDisplayName3 = paramDisplayName;
			m_paramDesc3 = (paramDesc == 0 ?  m_paramDisplayName3 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType3, ParamBaseType3, behaviac::Meta::IsAgent<ParamType3>::Result>::SetValue(this->m_param3, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType3>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid3 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min3 = rangeMin;
				this->m_max3 = rangeMax;
			}
		}
		else if (m_paramDisplayName4.empty())
		{
			m_paramDisplayName4 = paramDisplayName;
			m_paramDesc4 = (paramDesc == 0 ?  m_paramDisplayName4 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType4, ParamBaseType4, behaviac::Meta::IsAgent<ParamType4>::Result>::SetValue(this->m_param4, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType4>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid4 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min4 = rangeMin;
				this->m_max4 = rangeMax;
			}
		}
		else if (m_paramDisplayName5.empty())
		{
			m_paramDisplayName5 = paramDisplayName;
			m_paramDesc5 = (paramDesc == 0 ?  m_paramDisplayName5 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType5, ParamBaseType5, behaviac::Meta::IsAgent<ParamType5>::Result>::SetValue(this->m_param5, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType5>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid5 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min5 = rangeMin;
				this->m_max5 = rangeMax;
			}
		}
		else if (m_paramDisplayName6.empty())
		{
			m_paramDisplayName6 = paramDisplayName;
			m_paramDesc6 = (paramDesc == 0 ?  m_paramDisplayName6 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType6, ParamBaseType6, behaviac::Meta::IsAgent<ParamType6>::Result>::SetValue(this->m_param6, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType6>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid6 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min6 = rangeMin;
				this->m_max6 = rangeMax;
			}
		}
		else if (m_paramDisplayName7.empty())
		{
			m_paramDisplayName7 = paramDisplayName;
			m_paramDesc7 = (paramDesc == 0 ?  m_paramDisplayName7 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType7, ParamBaseType7, behaviac::Meta::IsAgent<ParamType7>::Result>::SetValue(this->m_param7, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType7>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid7 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min7 = rangeMin;
				this->m_max7 = rangeMax;
			}
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual int GetParams()
	{
		return 7;
	}

	virtual behaviac::string GetParamTypeName(uint32_t idx)
	{
		switch (idx)
		{
		case 0:
			{
				behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
				return typeStr1;
			}

		case 1:
			{
				behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
				return typeStr2;
			}

		case 2:
			{
				behaviac::string typeStr3 = ::GetTypeDescString<ParamType3>();
				return typeStr3;
			}

		case 3:
			{
				behaviac::string typeStr4 = ::GetTypeDescString<ParamType4>();
				return typeStr4;
			}

		case 4:
			{
				behaviac::string typeStr5 = ::GetTypeDescString<ParamType5>();
				return typeStr5;
			}

		case 5:
			{
				behaviac::string typeStr6 = ::GetTypeDescString<ParamType6>();
				return typeStr6;
			}

		case 6:
			{
				behaviac::string typeStr7 = ::GetTypeDescString<ParamType7>();
				return typeStr7;
			}

		default:
			return "";
		}
	}

	virtual void vCall(const CTagObject* parent, const void* param1, const void* param2, const void* param3, const void* param4, const void* param5, const void* param6, const void* param7)
	{
		(((ObjectType*)parent)->*this->m_methodPtr)(*(ParamPointerType1)param1, *(ParamPointerType2)param2, *(ParamPointerType3)param3, *(ParamPointerType4)param4, *(ParamPointerType5)param5, *(ParamPointerType6)param6, *(ParamPointerType7)param7);
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod7_(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
				const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
				const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);
				const StoredType7& v7 = this->m_param7.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4,
					(PARAM_CALLEDTYPE(ParamType5))v5,
					(PARAM_CALLEDTYPE(ParamType6))v6,
					(PARAM_CALLEDTYPE(ParamType7))v7);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
			const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
			const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);
			const StoredType7& v7 = this->m_param7.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1,
				(PARAM_CALLEDTYPE(ParamType2))v2,
				(PARAM_CALLEDTYPE(ParamType3))v3,
				(PARAM_CALLEDTYPE(ParamType4))v4,
				(PARAM_CALLEDTYPE(ParamType5))v5,
				(PARAM_CALLEDTYPE(ParamType6))v6,
				(PARAM_CALLEDTYPE(ParamType7))v7);

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
			this->m_param5.SetVariableRegistry(parHolder, v5);
			this->m_param6.SetVariableRegistry(parHolder, v6);
			this->m_param7.SetVariableRegistry(parHolder, v7);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 7);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);
		PARAM_BASETYPE(ParamType5) p5;
		params[4]->GetValue(p5);
		PARAM_BASETYPE(ParamType6) p6;
		params[5]->GetValue(p6);
		PARAM_BASETYPE(ParamType7) p7;
		params[6]->GetValue(p7);

		(((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3, 
			(PARAM_CALLEDTYPE(ParamType4))p4,
			(PARAM_CALLEDTYPE(ParamType5))p5,
			(PARAM_CALLEDTYPE(ParamType6))p6,
			(PARAM_CALLEDTYPE(ParamType7))p7);
	}
#endif//BEHAVIAC_ENABLE_NETWORKD

protected:
	R(ObjectType::*m_methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7);

	behaviac::wstring				m_paramDisplayName1;
	behaviac::wstring				m_paramDesc1;
	behaviac::wstring				m_paramDisplayName2;
	behaviac::wstring				m_paramDesc2;
	behaviac::wstring				m_paramDisplayName3;
	behaviac::wstring				m_paramDesc3;
	behaviac::wstring				m_paramDisplayName4;
	behaviac::wstring				m_paramDesc4;
	behaviac::wstring				m_paramDisplayName5;
	behaviac::wstring				m_paramDesc5;
	behaviac::wstring				m_paramDisplayName6;
	behaviac::wstring				m_paramDesc6;
	behaviac::wstring				m_paramDisplayName7;
	behaviac::wstring				m_paramDesc7;

	bool							m_paramRangeValid1;
	float							m_min1, m_max1;
	bool							m_paramRangeValid2;
	float							m_min2, m_max2;
	bool							m_paramRangeValid3;
	float							m_min3, m_max3;
	bool							m_paramRangeValid4;
	float							m_min4, m_max4;
	bool							m_paramRangeValid5;
	float							m_min5, m_max5;
	bool							m_paramRangeValid6;
	float							m_min6, m_max6;
	bool							m_paramRangeValid7;
	float							m_min7, m_max7;

	ParamVariable<StoredType1>		m_param1;
	ParamVariable<StoredType2>		m_param2;
	ParamVariable<StoredType3>		m_param3;
	ParamVariable<StoredType4>		m_param4;
	ParamVariable<StoredType5>		m_param5;
	ParamVariable<StoredType6>		m_param6;
	ParamVariable<StoredType7>		m_param7;
};


template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
class CGenericMethod7 : public CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>
{
public:
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType1 StoredType1;
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType2 StoredType2;
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType3 StoredType3;
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType4 StoredType4;
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType5 StoredType5;
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType6 StoredType6;
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType7 StoredType7;
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType2 ParamBaseType2;
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType3 ParamBaseType3;
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType4 ParamBaseType4;
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType5 ParamBaseType5;
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType6 ParamBaseType6;
	typedef typename CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType7 ParamBaseType7;

	CGenericMethod7(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7),
		const char* className, const char* propertyName) :
		CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>(methodPtr, className, propertyName)
	{}

	CGenericMethod7(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7) const,
		const char* className, const char* propertyName) :
		CGenericMethod7_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod7()
	{
	}

	virtual behaviac::Property* CreateProperty(const char* defaultValue, bool bConst) const
	{
		behaviac::Property* pProperty = behaviac::Property::Creator<R>(defaultValue, 0, bConst);

		return pProperty;
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod7(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
				const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
				const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);
				const StoredType7& v7 = this->m_param7.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4,
					(PARAM_CALLEDTYPE(ParamType5))v5,
					(PARAM_CALLEDTYPE(ParamType6))v6,
					(PARAM_CALLEDTYPE(ParamType7))v7);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
			const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
			const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);
			const StoredType7& v7 = this->m_param7.GetValue(parent, parHolder);

			R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1,
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3,
				(PARAM_CALLEDTYPE(ParamType4))v4,
				(PARAM_CALLEDTYPE(ParamType5))v5,
				(PARAM_CALLEDTYPE(ParamType6))v6,
				(PARAM_CALLEDTYPE(ParamType7))v7);

			if (this->m_return)
			{
				*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
			}

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
			this->m_param5.SetVariableRegistry(parHolder, v5);
			this->m_param6.SetVariableRegistry(parHolder, v6);
			this->m_param7.SetVariableRegistry(parHolder, v7);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 7);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);
		PARAM_BASETYPE(ParamType5) p5;
		params[4]->GetValue(p5);
		PARAM_BASETYPE(ParamType6) p6;
		params[5]->GetValue(p6);
		PARAM_BASETYPE(ParamType7) p7;
		params[6]->GetValue(p7);

		R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1,
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3,
			(PARAM_CALLEDTYPE(ParamType4))p4,
			(PARAM_CALLEDTYPE(ParamType5))p5,
			(PARAM_CALLEDTYPE(ParamType6))p6,
			(PARAM_CALLEDTYPE(ParamType7))p7);

		if (this->m_return)
		{
			*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
		}
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};

template<class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
class CGenericMethod7<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> : public CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>
{
public:
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType1 StoredType1;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType2 StoredType2;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType3 StoredType3;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType4 StoredType4;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType5 StoredType5;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType6 StoredType6;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType7 StoredType7;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::StoredType8 StoredType8;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType2 ParamBaseType2;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType3 ParamBaseType3;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType4 ParamBaseType4;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType5 ParamBaseType5;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType6 ParamBaseType6;
	typedef typename CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>::ParamBaseType7 ParamBaseType7;

	CGenericMethod7(void (ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7),
		const char* className, const char* propertyName) :
		CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>(methodPtr, className, propertyName)
	{}

	CGenericMethod7(void (ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7) const,
		const char* className, const char* propertyName) :
		CGenericMethod7_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod7()
	{
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod7(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
				const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
				const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);
				const StoredType7& v7 = this->m_param7.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4,
					(PARAM_CALLEDTYPE(ParamType5))v5,
					(PARAM_CALLEDTYPE(ParamType6))v6,
					(PARAM_CALLEDTYPE(ParamType7))v7);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
			const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
			const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);
			const StoredType7& v7 = this->m_param7.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1, 
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3, 
				(PARAM_CALLEDTYPE(ParamType4))v4,
				(PARAM_CALLEDTYPE(ParamType5))v5,
				(PARAM_CALLEDTYPE(ParamType6))v6,
				(PARAM_CALLEDTYPE(ParamType7))v7);

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
			this->m_param5.SetVariableRegistry(parHolder, v5);
			this->m_param6.SetVariableRegistry(parHolder, v6);
			this->m_param7.SetVariableRegistry(parHolder, v7);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 7);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);
		PARAM_BASETYPE(ParamType5) p5;
		params[4]->GetValue(p5);
		PARAM_BASETYPE(ParamType6) p6;
		params[5]->GetValue(p6);
		PARAM_BASETYPE(ParamType7) p7;
		params[6]->GetValue(p7);

		(((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3, 
			(PARAM_CALLEDTYPE(ParamType4))p4,
			(PARAM_CALLEDTYPE(ParamType5))p5,
			(PARAM_CALLEDTYPE(ParamType6))p6,
			(PARAM_CALLEDTYPE(ParamType7))p7);
	}
#endif//#if BEHAVIAC_ENABLE_NETWORKD
};

/////////////////////////////////////////////////////////
////////////////     CGenericMethod8_     ///////////////
/////////////////////////////////////////////////////////

template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
class CGenericMethod8_ : public CMethodBase
{
public:
	BEHAVIAC_DECLARE_MEMORY_OPERATORS(CGenericMethod8_);

	typedef PARAM_BASETYPE(ParamType1)				ParamBaseType1;
	typedef PARAM_BASETYPE(ParamType2)				ParamBaseType2;
	typedef PARAM_BASETYPE(ParamType3)				ParamBaseType3;
	typedef PARAM_BASETYPE(ParamType4)				ParamBaseType4;
	typedef PARAM_BASETYPE(ParamType5)				ParamBaseType5;
	typedef PARAM_BASETYPE(ParamType6)				ParamBaseType6;
	typedef PARAM_BASETYPE(ParamType7)				ParamBaseType7;
	typedef PARAM_BASETYPE(ParamType8)				ParamBaseType8;

	typedef PARAM_POINTERTYPE(ParamType1)			ParamPointerType1;
	typedef PARAM_POINTERTYPE(ParamType2)			ParamPointerType2;
	typedef PARAM_POINTERTYPE(ParamType3)			ParamPointerType3;
	typedef PARAM_POINTERTYPE(ParamType4)			ParamPointerType4;
	typedef PARAM_POINTERTYPE(ParamType5)			ParamPointerType5;
	typedef PARAM_POINTERTYPE(ParamType6)			ParamPointerType6;
	typedef PARAM_POINTERTYPE(ParamType7)			ParamPointerType7;
	typedef PARAM_POINTERTYPE(ParamType8)			ParamPointerType8;

	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType1>::Result, VALUE_TYPE(ParamType1), ParamBaseType1>::Result StoredType1;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType2>::Result, VALUE_TYPE(ParamType2), ParamBaseType2>::Result StoredType2;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType3>::Result, VALUE_TYPE(ParamType3), ParamBaseType3>::Result StoredType3;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType4>::Result, VALUE_TYPE(ParamType4), ParamBaseType4>::Result StoredType4;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType5>::Result, VALUE_TYPE(ParamType5), ParamBaseType5>::Result StoredType5;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType6>::Result, VALUE_TYPE(ParamType6), ParamBaseType6>::Result StoredType6;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType7>::Result, VALUE_TYPE(ParamType7), ParamBaseType7>::Result StoredType7;
	typedef typename behaviac::Meta::IfThenElse<behaviac::Meta::IsAgent<ParamType8>::Result, VALUE_TYPE(ParamType8), ParamBaseType8>::Result StoredType8;

	CGenericMethod8_(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8), 
		const char* className, const char* propertyName) :
		CMethodBase(propertyName, className), m_methodPtr(methodPtr),
		m_paramRangeValid1(false), m_paramRangeValid2(false), m_paramRangeValid3(false), m_paramRangeValid4(false), m_paramRangeValid5(false), m_paramRangeValid6(false), m_paramRangeValid7(false), m_paramRangeValid8(false),
		m_param1(), m_param2(), m_param3(), m_param4(), m_param5(), m_param6(), m_param7(), m_param8()
	{
	}

	typedef R (ObjectType::*MethodType_t)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8);

	CGenericMethod8_(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8) const, 
		const char* className, const char* propertyName) :
		CMethodBase(propertyName, className), m_methodPtr(MethodType_t(methodPtr)),
		m_paramRangeValid1(false), m_paramRangeValid2(false), m_paramRangeValid3(false), m_paramRangeValid4(false), m_paramRangeValid5(false), m_paramRangeValid6(false), m_paramRangeValid7(false), m_paramRangeValid8(false),
		m_param1(), m_param2(), m_param3(), m_param4(), m_param5(), m_param6(), m_param7(), m_param8()
	{
	}

	CGenericMethod8_(const CGenericMethod8_& copy) : CMethodBase(copy)
	{
		this->m_methodPtr = copy.m_methodPtr;

		this->m_paramDisplayName1 = copy.m_paramDisplayName1;
		this->m_paramDisplayName2 = copy.m_paramDisplayName2;
		this->m_paramDisplayName3 = copy.m_paramDisplayName3;
		this->m_paramDisplayName4 = copy.m_paramDisplayName4;
		this->m_paramDisplayName5 = copy.m_paramDisplayName5;
		this->m_paramDisplayName6 = copy.m_paramDisplayName6;
		this->m_paramDisplayName7 = copy.m_paramDisplayName7;
		this->m_paramDisplayName8 = copy.m_paramDisplayName8;

		this->m_param1 = copy.m_param1;
		this->m_param2 = copy.m_param2;
		this->m_param3 = copy.m_param3;
		this->m_param4 = copy.m_param4;
		this->m_param5 = copy.m_param5;
		this->m_param6 = copy.m_param6;
		this->m_param7 = copy.m_param7;
		this->m_param8 = copy.m_param8;
		this->m_paramRangeValid1 = copy.m_paramRangeValid1;
		this->m_paramRangeValid2 = copy.m_paramRangeValid2;
		this->m_paramRangeValid3 = copy.m_paramRangeValid3;
		this->m_paramRangeValid4 = copy.m_paramRangeValid4;
		this->m_paramRangeValid5 = copy.m_paramRangeValid5;
		this->m_paramRangeValid6 = copy.m_paramRangeValid6;
		this->m_paramRangeValid7 = copy.m_paramRangeValid7;
		this->m_paramRangeValid8 = copy.m_paramRangeValid8;
	}

	virtual void LoadFromXML(CTagObject* parent, const ISerializableNode& xmlNode)
	{
		this->m_param1.LoadFromXML(parent, xmlNode, "param1");
		this->m_param2.LoadFromXML(parent, xmlNode, "param2");
		this->m_param3.LoadFromXML(parent, xmlNode, "param3");
		this->m_param4.LoadFromXML(parent, xmlNode, "param4");
		this->m_param5.LoadFromXML(parent, xmlNode, "param5");
		this->m_param6.LoadFromXML(parent, xmlNode, "param6");
		this->m_param7.LoadFromXML(parent, xmlNode, "param7");
		this->m_param8.LoadFromXML(parent, xmlNode, "param8");
	}

	virtual void SaveToXML(const CTagObject* parent, ISerializableNode& xmlNode)
	{
		this->m_param1.SaveToXML(parent, xmlNode, "param1");
		this->m_param2.SaveToXML(parent, xmlNode, "param2");
		this->m_param3.SaveToXML(parent, xmlNode, "param3");
		this->m_param4.SaveToXML(parent, xmlNode, "param4");
		this->m_param5.SaveToXML(parent, xmlNode, "param5");
		this->m_param6.SaveToXML(parent, xmlNode, "param6");
		this->m_param7.SaveToXML(parent, xmlNode, "param7");
		this->m_param8.SaveToXML(parent, xmlNode, "param8");
	}

	virtual void GetUiInfo(CTagTypeDescriptor::TypesMap_t* types, const CTagObject* parent, const XmlNodeRef& xmlNode)
	{
		BEHAVIAC_UNUSED_VAR(parent);

		XmlNodeRef memberNode = xmlNode;
		if (types == NULL)
		{
			memberNode = xmlNode->newChild("Method");
			memberNode->setAttr("Name", this->m_propertyName);
			memberNode->setAttr("DisplayName", this->GetDisplayName());
			memberNode->setAttr("Desc", this->GetDesc());

			if (this->m_flag & CMethodBase::KMETHOD_NAMEDEVENT)
			{
				memberNode->setAttr("Flag", "namedevent");
			}
			if (this->m_classFullName)
			{
				memberNode->setAttr("Class", this->m_classFullName);
			}
			if (m_bStatic)
			{
				memberNode->setAttr("Static", "true");
			}
			if (this->IsActionMethodOnly())
			{
				memberNode->setAttr("IsActionMethodOnly", "true");
			}

			//const char* pReturn = GetClassTypeName((R*)0);
			//memberNode->setAttr("ReturnType", pReturn);
			behaviac::string returnTypeStr = ::GetTypeDescString<R>();
			memberNode->setAttr("ReturnType", returnTypeStr.c_str());
		}

		UserTypeInfoExport<R>::Export(types, true, memberNode);

		XmlNodeRef paramNode = memberNode;
		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName1);
			paramNode->setAttr("Desc", m_paramDesc1);

			behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
			paramNode->setAttr("Type", typeStr1.c_str());
			if (this->m_param1.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param1.GetValue());
			}
			if (m_paramRangeValid1)
			{
				paramNode->setAttr("RangeMin", m_min1);
				paramNode->setAttr("RangeMax", m_max1);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType1, behaviac::Meta::IsEnum<ParamBaseType1>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName2);
			paramNode->setAttr("Desc", m_paramDesc2);

			behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
			paramNode->setAttr("Type", typeStr2.c_str());
			if (this->m_param2.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param2.GetValue());
			}
			if (m_paramRangeValid2)
			{
				paramNode->setAttr("RangeMin", m_min2);
				paramNode->setAttr("RangeMax", m_max2);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType2, behaviac::Meta::IsEnum<ParamBaseType2>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName3);
			paramNode->setAttr("Desc", m_paramDesc3);

			behaviac::string typeStr3 = ::GetTypeDescString<ParamType3>();
			paramNode->setAttr("Type", typeStr3.c_str());
			if (this->m_param3.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param3.GetValue());
			}
			if (m_paramRangeValid3)
			{
				paramNode->setAttr("RangeMin", m_min3);
				paramNode->setAttr("RangeMax", m_max3);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType3, behaviac::Meta::IsEnum<ParamBaseType3>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName4);
			paramNode->setAttr("Desc", m_paramDesc4);

			behaviac::string typeStr4 = ::GetTypeDescString<ParamType4>();
			paramNode->setAttr("Type", typeStr4.c_str());
			if (this->m_param4.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param4.GetValue());
			}
			if (m_paramRangeValid4)
			{
				paramNode->setAttr("RangeMin", m_min4);
				paramNode->setAttr("RangeMax", m_max4);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType4, behaviac::Meta::IsEnum<ParamBaseType4>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName5);
			paramNode->setAttr("Desc", m_paramDesc5);

			behaviac::string typeStr5 = ::GetTypeDescString<ParamType5>();
			paramNode->setAttr("Type", typeStr5.c_str());
			if (this->m_param5.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param5.GetValue());
			}
			if (m_paramRangeValid5)
			{
				paramNode->setAttr("RangeMin", m_min5);
				paramNode->setAttr("RangeMax", m_max5);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType5, behaviac::Meta::IsEnum<ParamBaseType5>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName6);
			paramNode->setAttr("Desc", m_paramDesc6);

			behaviac::string typeStr6 = ::GetTypeDescString<ParamType6>();
			paramNode->setAttr("Type", typeStr6.c_str());
			if (this->m_param6.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param6.GetValue());
			}
			if (m_paramRangeValid6)
			{
				paramNode->setAttr("RangeMin", m_min6);
				paramNode->setAttr("RangeMax", m_max6);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType6, behaviac::Meta::IsEnum<ParamBaseType6>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName7);
			paramNode->setAttr("Desc", m_paramDesc7);

			behaviac::string typeStr7 = ::GetTypeDescString<ParamType7>();
			paramNode->setAttr("Type", typeStr7.c_str());
			if (this->m_param7.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param7.GetValue());
			}
			if (m_paramRangeValid7)
			{
				paramNode->setAttr("RangeMin", m_min7);
				paramNode->setAttr("RangeMax", m_max7);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType7, behaviac::Meta::IsEnum<ParamBaseType7>::Result>::GetUiInfo(types, paramNode);

		if (types == NULL)
		{
			paramNode = memberNode->newChild("Param");
			paramNode->setAttr("DisplayName", m_paramDisplayName8);
			paramNode->setAttr("Desc", m_paramDesc8);

			behaviac::string typeStr8 = ::GetTypeDescString<ParamType8>();
			paramNode->setAttr("Type", typeStr8.c_str());
			if (this->m_param8.IsDefaultValid())
			{
				paramNode->setAttr("Default", this->m_param8.GetValue());
			}
			if (m_paramRangeValid8)
			{
				paramNode->setAttr("RangeMin", m_min8);
				paramNode->setAttr("RangeMax", m_max8);
			}
		}

		EnumClassUiInfoGetter<ParamBaseType8, behaviac::Meta::IsEnum<ParamBaseType8>::Result>::GetUiInfo(types, paramNode);
	}

	virtual CMethodBase& PARAM_DISPLAYNAME(const wchar_t* paramDisplayName)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
		}
		else if (m_paramDisplayName3.empty())
		{
			m_paramDisplayName3 = paramDisplayName;
		}
		else if (m_paramDisplayName4.empty())
		{
			m_paramDisplayName4 = paramDisplayName;
		}
		else if (m_paramDisplayName5.empty())
		{
			m_paramDisplayName5 = paramDisplayName;
		}
		else if (m_paramDisplayName6.empty())
		{
			m_paramDisplayName6 = paramDisplayName;
		}
		else if (m_paramDisplayName7.empty())
		{
			m_paramDisplayName7 = paramDisplayName;
		}
		else if (m_paramDisplayName8.empty())
		{
			m_paramDisplayName8 = paramDisplayName;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DESC(const wchar_t* paramDesc)
	{
		BEHAVIAC_UNUSED_VAR(paramDesc);

		if (m_paramDesc1.empty())
		{
			m_paramDesc1 = paramDesc;
		}
		else if (m_paramDesc2.empty())
		{
			m_paramDesc2 = paramDesc;
		}
		else if (m_paramDesc3.empty())
		{
			m_paramDesc3 = paramDesc;
		}
		else if (m_paramDesc4.empty())
		{
			m_paramDesc4 = paramDesc;
		}
		else if (m_paramDesc5.empty())
		{
			m_paramDesc5 = paramDesc;
		}
		else if (m_paramDesc6.empty())
		{
			m_paramDesc6 = paramDesc;
		}
		else if (m_paramDesc7.empty())
		{
			m_paramDesc7 = paramDesc;
		}
		else if (m_paramDesc8.empty())
		{
			m_paramDesc8 = paramDesc;
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual CMethodBase& PARAM_DISPLAY_INFO(const wchar_t* paramDisplayName, const wchar_t* paramDesc = 0, const DefaultParam_t& defaultParam = DefaultParam_t(), float rangeMin = CMETHODBASE_RANGE_MIN_DEFAULT, float rangeMax = CMETHODBASE_RANGE_MAX_DEFAULT)
	{
		BEHAVIAC_UNUSED_VAR(paramDisplayName);
		BEHAVIAC_UNUSED_VAR(paramDesc);
		BEHAVIAC_UNUSED_VAR(defaultParam);
		BEHAVIAC_UNUSED_VAR(rangeMin);
		BEHAVIAC_UNUSED_VAR(rangeMax);

		if (m_paramDisplayName1.empty())
		{
			m_paramDisplayName1 = paramDisplayName;
			m_paramDesc1 = (paramDesc == 0 ?  m_paramDisplayName1 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType1, ParamBaseType1, behaviac::Meta::IsAgent<ParamType1>::Result>::SetValue(this->m_param1, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType1>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid1 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min1 = rangeMin;
				this->m_max1 = rangeMax;
			}
		}
		else if (m_paramDisplayName2.empty())
		{
			m_paramDisplayName2 = paramDisplayName;
			m_paramDesc2 = (paramDesc == 0 ?  m_paramDisplayName2 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType2, ParamBaseType2, behaviac::Meta::IsAgent<ParamType2>::Result>::SetValue(this->m_param2, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType2>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid2 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min2 = rangeMin;
				this->m_max2 = rangeMax;
			}
		}
		else if (m_paramDisplayName3.empty())
		{
			m_paramDisplayName3 = paramDisplayName;
			m_paramDesc3 = (paramDesc == 0 ?  m_paramDisplayName3 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType3, ParamBaseType3, behaviac::Meta::IsAgent<ParamType3>::Result>::SetValue(this->m_param3, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType3>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid3 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min3 = rangeMin;
				this->m_max3 = rangeMax;
			}
		}
		else if (m_paramDisplayName4.empty())
		{
			m_paramDisplayName4 = paramDisplayName;
			m_paramDesc4 = (paramDesc == 0 ?  m_paramDisplayName4 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType4, ParamBaseType4, behaviac::Meta::IsAgent<ParamType4>::Result>::SetValue(this->m_param4, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType4>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid4 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min4 = rangeMin;
				this->m_max4 = rangeMax;
			}
		}
		else if (m_paramDisplayName5.empty())
		{
			m_paramDisplayName5 = paramDisplayName;
			m_paramDesc5 = (paramDesc == 0 ?  m_paramDisplayName5 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType5, ParamBaseType5, behaviac::Meta::IsAgent<ParamType5>::Result>::SetValue(this->m_param5, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType5>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid5 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min5 = rangeMin;
				this->m_max5 = rangeMax;
			}
		}
		else if (m_paramDisplayName6.empty())
		{
			m_paramDisplayName6 = paramDisplayName;
			m_paramDesc6 = (paramDesc == 0 ?  m_paramDisplayName6 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType6, ParamBaseType6, behaviac::Meta::IsAgent<ParamType6>::Result>::SetValue(this->m_param6, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType6>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid6 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min6 = rangeMin;
				this->m_max6 = rangeMax;
			}
		}
		else if (m_paramDisplayName7.empty())
		{
			m_paramDisplayName7 = paramDisplayName;
			m_paramDesc7 = (paramDesc == 0 ?  m_paramDisplayName7 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType7, ParamBaseType7, behaviac::Meta::IsAgent<ParamType7>::Result>::SetValue(this->m_param7, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType7>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid7 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min7 = rangeMin;
				this->m_max7 = rangeMax;
			}
		}
		else if (m_paramDisplayName8.empty())
		{
			m_paramDisplayName8 = paramDisplayName;
			m_paramDesc8 = (paramDesc == 0 ?  m_paramDisplayName8 : paramDesc);

			if (defaultParam.IsValid())
			{
				DefaulParamSetValueSelector<StoredType8, ParamBaseType8, behaviac::Meta::IsAgent<ParamType8>::Result>::SetValue(this->m_param8, defaultParam);;
			}

			int typeId = GetClassTypeNumberId<ParamBaseType8>();
			if (IsNumberClassTypeNumberId(typeId))
			{
				BEHAVIAC_ASSERT(rangeMin <= rangeMax);
				this->m_paramRangeValid8 = (rangeMin != CMETHODBASE_RANGE_MIN_DEFAULT && rangeMax != CMETHODBASE_RANGE_MAX_DEFAULT);
				this->m_min8 = rangeMin;
				this->m_max8 = rangeMax;
			}
		}
		else
		{
			BEHAVIAC_ASSERT(0, "too many params!");
		}

		return *this;
	}

	virtual int GetParams()
	{
		return 8;
	}

	virtual behaviac::string GetParamTypeName(uint32_t idx)
	{
		switch (idx)
		{
		case 0:
			{
				behaviac::string typeStr1 = ::GetTypeDescString<ParamType1>();
				return typeStr1;
			}

		case 1:
			{
				behaviac::string typeStr2 = ::GetTypeDescString<ParamType2>();
				return typeStr2;
			}

		case 2:
			{
				behaviac::string typeStr3 = ::GetTypeDescString<ParamType3>();
				return typeStr3;
			}

		case 3:
			{
				behaviac::string typeStr4 = ::GetTypeDescString<ParamType4>();
				return typeStr4;
			}

		case 4:
			{
				behaviac::string typeStr5 = ::GetTypeDescString<ParamType5>();
				return typeStr5;
			}

		case 5:
			{
				behaviac::string typeStr6 = ::GetTypeDescString<ParamType6>();
				return typeStr6;
			}

		case 6:
			{
				behaviac::string typeStr7 = ::GetTypeDescString<ParamType7>();
				return typeStr7;
			}

		case 7:
			{
				behaviac::string typeStr8 = ::GetTypeDescString<ParamType8>();
				return typeStr8;
			}

		default:
			return "";
		}
	}

	virtual void vCall(const CTagObject* parent, const void* param1, const void* param2, const void* param3, const void* param4, const void* param5, const void* param6, const void* param7, const void* param8)
	{
		(((ObjectType*)parent)->*this->m_methodPtr)(*(ParamPointerType1)param1, *(ParamPointerType2)param2, *(ParamPointerType3)param3, *(ParamPointerType4)param4, *(ParamPointerType5)param5, *(ParamPointerType6)param6, *(ParamPointerType7)param7, *(ParamPointerType8)param8);
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod8_(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
				const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
				const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);
				const StoredType7& v7 = this->m_param7.GetValue(parent, parHolder);
				const StoredType8& v8 = this->m_param8.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4,
					(PARAM_CALLEDTYPE(ParamType5))v5,
					(PARAM_CALLEDTYPE(ParamType6))v6,
					(PARAM_CALLEDTYPE(ParamType7))v7,
					(PARAM_CALLEDTYPE(ParamType8))v8);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
			const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
			const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);
			const StoredType7& v7 = this->m_param7.GetValue(parent, parHolder);
			const StoredType8& v8 = this->m_param8.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1,
				(PARAM_CALLEDTYPE(ParamType2))v2,
				(PARAM_CALLEDTYPE(ParamType3))v3,
				(PARAM_CALLEDTYPE(ParamType4))v4,
				(PARAM_CALLEDTYPE(ParamType5))v5,
				(PARAM_CALLEDTYPE(ParamType6))v6,
				(PARAM_CALLEDTYPE(ParamType7))v7,
				(PARAM_CALLEDTYPE(ParamType8))v8);

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
			this->m_param5.SetVariableRegistry(parHolder, v5);
			this->m_param6.SetVariableRegistry(parHolder, v6);
			this->m_param7.SetVariableRegistry(parHolder, v7);
			this->m_param8.SetVariableRegistry(parHolder, v8);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 8);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);
		PARAM_BASETYPE(ParamType5) p5;
		params[4]->GetValue(p5);
		PARAM_BASETYPE(ParamType6) p6;
		params[5]->GetValue(p6);
		PARAM_BASETYPE(ParamType7) p7;
		params[6]->GetValue(p7);
		PARAM_BASETYPE(ParamType8) p8;
		params[7]->GetValue(p8);

		(((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3, 
			(PARAM_CALLEDTYPE(ParamType4))p4,
			(PARAM_CALLEDTYPE(ParamType5))p5,
			(PARAM_CALLEDTYPE(ParamType6))p6,
			(PARAM_CALLEDTYPE(ParamType7))p7,
			(PARAM_CALLEDTYPE(ParamType8))p8);
	}
#endif//BEHAVIAC_ENABLE_NETWORKD

protected:
	R(ObjectType::*m_methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8);

	behaviac::wstring				m_paramDisplayName1;
	behaviac::wstring				m_paramDesc1;
	behaviac::wstring				m_paramDisplayName2;
	behaviac::wstring				m_paramDesc2;
	behaviac::wstring				m_paramDisplayName3;
	behaviac::wstring				m_paramDesc3;
	behaviac::wstring				m_paramDisplayName4;
	behaviac::wstring				m_paramDesc4;
	behaviac::wstring				m_paramDisplayName5;
	behaviac::wstring				m_paramDesc5;
	behaviac::wstring				m_paramDisplayName6;
	behaviac::wstring				m_paramDesc6;
	behaviac::wstring				m_paramDisplayName7;
	behaviac::wstring				m_paramDesc7;
	behaviac::wstring				m_paramDisplayName8;
	behaviac::wstring				m_paramDesc8;

	bool							m_paramRangeValid1;
	float							m_min1, m_max1;
	bool							m_paramRangeValid2;
	float							m_min2, m_max2;
	bool							m_paramRangeValid3;
	float							m_min3, m_max3;
	bool							m_paramRangeValid4;
	float							m_min4, m_max4;
	bool							m_paramRangeValid5;
	float							m_min5, m_max5;
	bool							m_paramRangeValid6;
	float							m_min6, m_max6;
	bool							m_paramRangeValid7;
	float							m_min7, m_max7;
	bool							m_paramRangeValid8;
	float							m_min8, m_max8;

	ParamVariable<StoredType1>		m_param1;
	ParamVariable<StoredType2>		m_param2;
	ParamVariable<StoredType3>		m_param3;
	ParamVariable<StoredType4>		m_param4;
	ParamVariable<StoredType5>		m_param5;
	ParamVariable<StoredType6>		m_param6;
	ParamVariable<StoredType7>		m_param7;
	ParamVariable<StoredType8>		m_param8;
};


template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
class CGenericMethod8 : public CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>
{
public:
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType1 StoredType1;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType2 StoredType2;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType3 StoredType3;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType4 StoredType4;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType5 StoredType5;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType6 StoredType6;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType7 StoredType7;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType8 StoredType8;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType2 ParamBaseType2;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType3 ParamBaseType3;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType4 ParamBaseType4;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType5 ParamBaseType5;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType6 ParamBaseType6;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType7 ParamBaseType7;
	typedef typename CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType8 ParamBaseType8;

	CGenericMethod8(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8),
		const char* className, const char* propertyName) :
		CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>(methodPtr, className, propertyName)
	{}

	CGenericMethod8(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8) const,
		const char* className, const char* propertyName) :
		CGenericMethod8_<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod8()
	{
	}

	virtual behaviac::Property* CreateProperty(const char* defaultValue, bool bConst) const
	{
		behaviac::Property* pProperty = behaviac::Property::Creator<R>(defaultValue, 0, bConst);

		return pProperty;
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod8(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
				const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
				const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);
				const StoredType7& v7 = this->m_param7.GetValue(parent, parHolder);
				const StoredType8& v8 = this->m_param8.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4,
					(PARAM_CALLEDTYPE(ParamType5))v5,
					(PARAM_CALLEDTYPE(ParamType6))v6,
					(PARAM_CALLEDTYPE(ParamType7))v7,
					(PARAM_CALLEDTYPE(ParamType8))v8);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
			const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
			const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);
			const StoredType7& v7 = this->m_param7.GetValue(parent, parHolder);
			const StoredType8& v8 = this->m_param8.GetValue(parent, parHolder);

			R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1,
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3,
				(PARAM_CALLEDTYPE(ParamType4))v4,
				(PARAM_CALLEDTYPE(ParamType5))v5,
				(PARAM_CALLEDTYPE(ParamType6))v6,
				(PARAM_CALLEDTYPE(ParamType7))v7,
				(PARAM_CALLEDTYPE(ParamType8))v8);

			if (this->m_return)
			{
				*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
			}

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
			this->m_param5.SetVariableRegistry(parHolder, v5);
			this->m_param6.SetVariableRegistry(parHolder, v6);
			this->m_param7.SetVariableRegistry(parHolder, v7);
			this->m_param8.SetVariableRegistry(parHolder, v8);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 8);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);
		PARAM_BASETYPE(ParamType5) p5;
		params[4]->GetValue(p5);
		PARAM_BASETYPE(ParamType6) p6;
		params[5]->GetValue(p6);
		PARAM_BASETYPE(ParamType7) p7;
		params[6]->GetValue(p7);
		PARAM_BASETYPE(ParamType8) p8;
		params[7]->GetValue(p8);

		R returnValue = (((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1,
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3,
			(PARAM_CALLEDTYPE(ParamType4))p4,
			(PARAM_CALLEDTYPE(ParamType5))p5,
			(PARAM_CALLEDTYPE(ParamType6))p6,
			(PARAM_CALLEDTYPE(ParamType7))p7,
			(PARAM_CALLEDTYPE(ParamType8))p8);

		if (this->m_return)
		{
			*(behaviac::AsyncValue<R>*)this->m_return = returnValue;
		}
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};

template<class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
class CGenericMethod8<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> : public CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>
{
public:
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType1 StoredType1;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType2 StoredType2;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType3 StoredType3;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType4 StoredType4;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType5 StoredType5;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType6 StoredType6;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType7 StoredType7;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::StoredType8 StoredType8;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType1 ParamBaseType1;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType2 ParamBaseType2;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType3 ParamBaseType3;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType4 ParamBaseType4;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType5 ParamBaseType5;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType6 ParamBaseType6;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType7 ParamBaseType7;
	typedef typename CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>::ParamBaseType8 ParamBaseType8;

	CGenericMethod8(void (ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8),
		const char* className, const char* propertyName) :
		CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>(methodPtr, className, propertyName)
	{}

	CGenericMethod8(void (ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8) const,
		const char* className, const char* propertyName) :
		CGenericMethod8_<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>(methodPtr, className, propertyName)
	{}

	virtual ~CGenericMethod8()
	{
	}

	virtual CMethodBase* clone() const
	{
		return BEHAVIAC_NEW CGenericMethod8(*this);
	}

	virtual void run(const CTagObject* parent, const CTagObject* parHolder)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);
#if BEHAVIAC_ENABLE_NETWORKD
		bool bHandled = false;
		if (this->m_netRole != behaviac::NET_ROLE_DEFAULT)
		{
			behaviac::Network* pNw = behaviac::Network::GetInstance();
			if (pNw && !pNw->IsSinglePlayer())
			{
				behaviac::string nameTemp;

				if (this->m_className)
				{
					nameTemp = FormatString("%s::%s", this->m_className, this->m_propertyName);
				}
				else
				{
					nameTemp = this->m_propertyName;
				}

				const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
				const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
				const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
				const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
				const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
				const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);
				const StoredType7& v7 = this->m_param7.GetValue(parent, parHolder);
				const StoredType8& v8 = this->m_param8.GetValue(parent, parHolder);

				bHandled = pNw->SendRemoteEvent<ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8>(this->m_netRole, nameTemp.c_str(), 
					(PARAM_CALLEDTYPE(ParamType1))v1, 
					(PARAM_CALLEDTYPE(ParamType2))v2, 
					(PARAM_CALLEDTYPE(ParamType3))v3, 
					(PARAM_CALLEDTYPE(ParamType4))v4,
					(PARAM_CALLEDTYPE(ParamType5))v5,
					(PARAM_CALLEDTYPE(ParamType6))v6,
					(PARAM_CALLEDTYPE(ParamType7))v7,
					(PARAM_CALLEDTYPE(ParamType8))v8);
			}
		}

		if (!bHandled)
#endif//#if BEHAVIAC_ENABLE_NETWORKD
		{
			const StoredType1& v1 = this->m_param1.GetValue(parent, parHolder);
			const StoredType2& v2 = this->m_param2.GetValue(parent, parHolder);
			const StoredType3& v3 = this->m_param3.GetValue(parent, parHolder);
			const StoredType4& v4 = this->m_param4.GetValue(parent, parHolder);
			const StoredType5& v5 = this->m_param5.GetValue(parent, parHolder);
			const StoredType6& v6 = this->m_param6.GetValue(parent, parHolder);
			const StoredType7& v7 = this->m_param7.GetValue(parent, parHolder);
			const StoredType8& v8 = this->m_param8.GetValue(parent, parHolder);

			(((ObjectType*)parent)->*this->m_methodPtr)(
				(PARAM_CALLEDTYPE(ParamType1))v1, 
				(PARAM_CALLEDTYPE(ParamType2))v2, 
				(PARAM_CALLEDTYPE(ParamType3))v3, 
				(PARAM_CALLEDTYPE(ParamType4))v4,
				(PARAM_CALLEDTYPE(ParamType5))v5,
				(PARAM_CALLEDTYPE(ParamType6))v6,
				(PARAM_CALLEDTYPE(ParamType7))v7,
				(PARAM_CALLEDTYPE(ParamType8))v8);

			this->m_param1.SetVariableRegistry(parHolder, v1);
			this->m_param2.SetVariableRegistry(parHolder, v2);
			this->m_param3.SetVariableRegistry(parHolder, v3);
			this->m_param4.SetVariableRegistry(parHolder, v4);
			this->m_param5.SetVariableRegistry(parHolder, v5);
			this->m_param6.SetVariableRegistry(parHolder, v6);
			this->m_param7.SetVariableRegistry(parHolder, v7);
			this->m_param8.SetVariableRegistry(parHolder, v8);
		}
	}

#if BEHAVIAC_ENABLE_NETWORKD
	virtual void run(const CTagObject* parent, const CTagObject* parHolder, const behaviac::Variants_t& params)
	{
		BEHAVIAC_UNUSED_VAR(parent);
		BEHAVIAC_UNUSED_VAR(parHolder);

		BEHAVIAC_ASSERT(params.size() == 7);

		PARAM_BASETYPE(ParamType1) p1;
		params[0]->GetValue(p1);
		PARAM_BASETYPE(ParamType2) p2;
		params[1]->GetValue(p2);
		PARAM_BASETYPE(ParamType3) p3;
		params[2]->GetValue(p3);
		PARAM_BASETYPE(ParamType4) p4;
		params[3]->GetValue(p4);
		PARAM_BASETYPE(ParamType5) p5;
		params[4]->GetValue(p5);
		PARAM_BASETYPE(ParamType6) p6;
		params[5]->GetValue(p6);
		PARAM_BASETYPE(ParamType7) p7;
		params[6]->GetValue(p7);
		PARAM_BASETYPE(ParamType8) p8;
		params[7]->GetValue(p8);

		(((ObjectType*)parent)->*this->m_methodPtr)(
			(PARAM_CALLEDTYPE(ParamType1))p1, 
			(PARAM_CALLEDTYPE(ParamType2))p2, 
			(PARAM_CALLEDTYPE(ParamType3))p3, 
			(PARAM_CALLEDTYPE(ParamType4))p4,
			(PARAM_CALLEDTYPE(ParamType5))p5,
			(PARAM_CALLEDTYPE(ParamType6))p6,
			(PARAM_CALLEDTYPE(ParamType7))p7,
			(PARAM_CALLEDTYPE(ParamType8))p8);
	}
#endif//BEHAVIAC_ENABLE_NETWORKD
};

#include "behaviac/base/object/staticmethod.h"

struct CMethodFactory
{
	template<typename R, class ObjectType>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(void), const char* className, const char* propertyName)
	{
		typedef CGenericMethod<R, ObjectType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename R, class ObjectType>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(void) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod<R, ObjectType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(void), const char* className, const char* propertyName)
	{
		typedef CGenericMethod<R, ObjectType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(void), const char* className, const char* propertyName)
	{
		typedef CGenericMethod<R, ObjectType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(void) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod<R, ObjectType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(void) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod<R, ObjectType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ObjectType>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(void), void (ObjectType::*methodPtr)(void), const char* className, const char* propertyName)
	{
		typedef CGenericMethod<void, ObjectType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType>
	static CMethodBase& Create(CR(*checkResultPtr)(void), void (ObjectType::*methodPtr)(void), const char* className, const char* propertyName)
	{
		typedef CGenericMethod<void, ObjectType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}


	template<typename CR, class ObjectType>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(void), void (ObjectType::*methodPtr)(void) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod<void, ObjectType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType>
	static CMethodBase& Create(CR(*checkResultPtr)(void), void (ObjectType::*methodPtr)(void) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod<void, ObjectType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType), const char* className, const char* propertyName)
	{
		typedef CGenericMethod1<R, ObjectType, ParamType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod1<R, ObjectType, ParamType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType), const char* className, const char* propertyName)
	{
		typedef CGenericMethod1<R, ObjectType, ParamType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType), const char* className, const char* propertyName)
	{
		typedef CGenericMethod1<R, ObjectType, ParamType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod1<R, ObjectType, ParamType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod1<R, ObjectType, ParamType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ObjectType, class ParamType>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(void), void (ObjectType::*methodPtr)(ParamType), const char* className, const char* propertyName)
	{
		typedef CGenericMethod1<void, ObjectType, ParamType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType>
	static CMethodBase& Create(CR(*checkResultPtr)(void), void (ObjectType::*methodPtr)(ParamType), const char* className, const char* propertyName)
	{
		typedef CGenericMethod1<void, ObjectType, ParamType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ObjectType, class ParamType>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(void), void (ObjectType::*methodPtr)(ParamType) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod1<void, ObjectType, ParamType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ObjectType, class ParamType>
	static CMethodBase& Create(CR(*checkResultPtr)(void), void (ObjectType::*methodPtr)(ParamType) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod1<void, ObjectType, ParamType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2), const char* className, const char* propertyName)
	{
		typedef CGenericMethod2<R, ObjectType, ParamType1, ParamType2> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod2<R, ObjectType, ParamType1, ParamType2> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2), const char* className, const char* propertyName)
	{
		typedef CGenericMethod2<R, ObjectType, ParamType1, ParamType2> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2), const char* className, const char* propertyName)
	{
		typedef CGenericMethod2<R, ObjectType, ParamType1, ParamType2> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod2<R, ObjectType, ParamType1, ParamType2> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod2<R, ObjectType, ParamType1, ParamType2> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ObjectType, class ParamType1, class ParamType2>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void (ObjectType::*methodPtr)(ParamType1, ParamType2), const char* className, const char* propertyName)
	{
		typedef CGenericMethod2<void, ObjectType, ParamType1, ParamType2> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2>
	static CMethodBase& Create(CR(*checkResultPtr)(), void (ObjectType::*methodPtr)(ParamType1, ParamType2), const char* className, const char* propertyName)
	{
		typedef CGenericMethod2<void, ObjectType, ParamType1, ParamType2> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void (ObjectType::*methodPtr)(ParamType1, ParamType2) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod2<void, ObjectType, ParamType1, ParamType2> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2>
	static CMethodBase& Create(CR(*checkResultPtr)(), void (ObjectType::*methodPtr)(ParamType1, ParamType2) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod2<void, ObjectType, ParamType1, ParamType2> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3), const char* className, const char* propertyName)
	{
		typedef CGenericMethod3<R, ObjectType, ParamType1, ParamType2, ParamType3> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod3<R, ObjectType, ParamType1, ParamType2, ParamType3> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3), const char* className, const char* propertyName)
	{
		typedef CGenericMethod3<R, ObjectType, ParamType1, ParamType2, ParamType3> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3), const char* className, const char* propertyName)
	{
		typedef CGenericMethod3<R, ObjectType, ParamType1, ParamType2, ParamType3> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod3<R, ObjectType, ParamType1, ParamType2, ParamType3> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod3<R, ObjectType, ParamType1, ParamType2, ParamType3> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3), const char* className, const char* propertyName)
	{
		typedef CGenericMethod3<void, ObjectType, ParamType1, ParamType2, ParamType3> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3), const char* className, const char* propertyName)
	{
		typedef CGenericMethod3<void, ObjectType, ParamType1, ParamType2, ParamType3> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod3<void, ObjectType, ParamType1, ParamType2, ParamType3> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod3<void, ObjectType, ParamType1, ParamType2, ParamType3> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4), const char* className, const char* propertyName)
	{
		typedef CGenericMethod4<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod4<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4), const char* className, const char* propertyName)
	{
		typedef CGenericMethod4<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4), const char* className, const char* propertyName)
	{
		typedef CGenericMethod4<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod4<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod4<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4), const char* className, const char* propertyName)
	{
		typedef CGenericMethod4<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4), const char* className, const char* propertyName)
	{
		typedef CGenericMethod4<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod4<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod4<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5), const char* className, const char* propertyName)
	{
		typedef CGenericMethod5<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod5<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5), const char* className, const char* propertyName)
	{
		typedef CGenericMethod5<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5), const char* className, const char* propertyName)
	{
		typedef CGenericMethod5<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod5<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod5<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5), const char* className, const char* propertyName)
	{
		typedef CGenericMethod5<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5), const char* className, const char* propertyName)
	{
		typedef CGenericMethod5<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod5<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod5<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6), const char* className, const char* propertyName)
	{
		typedef CGenericMethod6<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod6<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6), const char* className, const char* propertyName)
	{
		typedef CGenericMethod6<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6), const char* className, const char* propertyName)
	{
		typedef CGenericMethod6<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod6<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod6<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6), const char* className, const char* propertyName)
	{
		typedef CGenericMethod6<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6), const char* className, const char* propertyName)
	{
		typedef CGenericMethod6<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod6<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod6<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7), const char* className, const char* propertyName)
	{
		typedef CGenericMethod7<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod7<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7), const char* className, const char* propertyName)
	{
		typedef CGenericMethod7<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7), const char* className, const char* propertyName)
	{
		typedef CGenericMethod7<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod7<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod7<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7), const char* className, const char* propertyName)
	{
		typedef CGenericMethod7<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7), const char* className, const char* propertyName)
	{
		typedef CGenericMethod7<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod7<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod7<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8), const char* className, const char* propertyName)
	{
		typedef CGenericMethod8<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
	static CMethodBase& Create(R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod8<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8), const char* className, const char* propertyName)
	{
		typedef CGenericMethod8<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8), const char* className, const char* propertyName)
	{
		typedef CGenericMethod8<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod8<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, typename R, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod8<R, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8), const char* className, const char* propertyName)
	{
		typedef CGenericMethod8<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8), const char* className, const char* propertyName)
	{
		typedef CGenericMethod8<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
	static CMethodBase& Create(CR(ObjectType::*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod8<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	template<typename CR, class ObjectType, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(ObjectType::*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8) const, const char* className, const char* propertyName)
	{
		typedef CGenericMethod8<void, ObjectType, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	template<typename R>
	static CMethodBase& Create(R(*methodPtr)(void), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic<R> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(*methodPtr)(void), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic<R> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR>
	static CMethodBase& Create(CR(*checkResultPtr)(void), void (*methodPtr)(void), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic<void> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ParamType>
	static CMethodBase& Create(R(*methodPtr)(ParamType), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic1<R, ParamType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ParamType>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(*methodPtr)(ParamType), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic1<R, ParamType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ParamType>
	static CMethodBase& Create(CR(*checkResultPtr)(void), void (*methodPtr)(ParamType), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic1<void, ParamType> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ParamType1, class ParamType2>
	static CMethodBase& Create(R(*methodPtr)(ParamType1, ParamType2), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic2<R, ParamType1, ParamType2> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ParamType1, class ParamType2>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(*methodPtr)(ParamType1, ParamType2), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic2<R, ParamType1, ParamType2> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ParamType1, class ParamType2>
	static CMethodBase& Create(CR(*checkResultPtr)(), void (*methodPtr)(ParamType1, ParamType2), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic2<void, ParamType1, ParamType2> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}


	template<typename R, class ParamType1, class ParamType2, class ParamType3>
	static CMethodBase& Create(R(*methodPtr)(ParamType1, ParamType2, ParamType3), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic3<R, ParamType1, ParamType2, ParamType3> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}


	template<typename CR, typename R, class ParamType1, class ParamType2, class ParamType3>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(*methodPtr)(ParamType1, ParamType2, ParamType3), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic3<R, ParamType1, ParamType2, ParamType3> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ParamType1, class ParamType2, class ParamType3>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(*methodPtr)(ParamType1, ParamType2, ParamType3), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic3<void, ParamType1, ParamType2, ParamType3> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
	static CMethodBase& Create(R(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic4<R, ParamType1, ParamType2, ParamType3, ParamType4> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic4<R, ParamType1, ParamType2, ParamType3, ParamType4> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ParamType1, class ParamType2, class ParamType3, class ParamType4>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic4<void, ParamType1, ParamType2, ParamType3, ParamType4> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
	static CMethodBase& Create(R(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic5<R, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic5<R, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic5<void, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
	static CMethodBase& Create(R(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic6<R, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic6<R, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic6<void, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
	static CMethodBase& Create(R(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic7<R, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic7<R, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic7<void, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename R, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
	static CMethodBase& Create(R(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic8<R, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder<R>();
		return *pMethod;
	}

	template<typename CR, typename R, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
	static CMethodBase& Create(CR(*checkResultPtr)(R), R(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic8<R, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}

	template<typename CR, class ParamType1, class ParamType2, class ParamType3, class ParamType4, class ParamType5, class ParamType6, class ParamType7, class ParamType8>
	static CMethodBase& Create(CR(*checkResultPtr)(), void(*methodPtr)(ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8), const char* className, const char* propertyName)
	{
		typedef CGenericMethodStatic8<void, ParamType1, ParamType2, ParamType3, ParamType4, ParamType5, ParamType6, ParamType7, ParamType8> MethodType;
		CMethodBase* pMethod = BEHAVIAC_NEW MethodType(methodPtr, className, propertyName);
		pMethod->AddResultHanlder(checkResultPtr);
		return *pMethod;
	}
};

#endif // #ifndef _ENGINESERVICES_METHOD_H_
